zoukankan      html  css  js  c++  java
  • JVM内存管理------GC简介

    为何要了解GC策略与原理?

             

            原因在上一章其实已经有所触及,就是因为在平时的工作和研究当中,不可避免的会遇到内存溢出与内存泄露的问题。如果对GC策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让人不知所措。

            当我们了解了相关知识以后,虽然有时候依然不能很快的解决问题,但可以肯定的是,至少不会出现无计可施的情况。

     

    GC策略解决了哪些问题?

         

            既然是要进行自动GC,那必然会有相应的策略,而这些策略解决了哪些问题呢,粗略的来说,主要有以下几点。

            1、哪些对象可以被回收。

            2、何时回收这些对象。

            3、采用什么样的方式回收。

            

    GC策略采用的何种算法

          

            有关上面所提到的三个问题,其实最主要的一个问题就是第一个,也就是哪些对象才是可以回收的。

            有一种比较简单直观的办法,它的效率较高,被称作引用计数算法。但是这个算法有一个致命的缺陷,那就是对于循环引用的对象无法进行回收。想象一下,假设JVM采用这种GC策略,那么程序猿在编写的程序的时候,下面这样的代码就不要指望再出现了。

    public class Object {
    
        Object field = null;
        
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    Object objectA = new Object();
                    Object objectB = new Object();//1
                    objectA.field = objectB;
                    objectB.field = objectA;//2
                    //to do something
                    objectA = null;
                    objectB = null;//3
                }
            });
            thread.start();
            while (true);
        }
        
    }

    这段代码看起来有点刻意为之,但其实在实际编程过程当中,是经常出现的,比如两个一对一关系的数据库对象,各自保持着对方的引用。最后一个无限循环只是为了保持JVM不退出,没什么实际意义。

             对于我们现在使用的GC来说,当thread线程运行结束后,会将objectA和objectB全部作为待回收的对象。而如果我们的GC采用上面所说的引用计数算法,则这两个对象永远不会被回收,即便我们在使用后显示的将对象归为空值也毫无作用。

             这里LZ大致解释一下,在代码中LZ标注了1、2、3三个数字,当第1个地方的语句执行完以后,两个对象的引用计数全部为1。当第2个地方的语句执行完以后,两个对象的引用计数就全部变成了2。当第3个地方的语句执行完以后,也就是将二者全部归为空值以后,二者的引用计数仍然为1。根据引用计数算法的回收规则,引用计数没有归0的时候是不会被回收的。

             

    根搜索算法

           

             由于引用计数算法的缺陷,所以JVM一般会采用一种新的算法,叫做根搜索算法。它的处理方式就是,设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的

             就拿上图来说,ObjectD和ObjectE是互相关联的,但是由于GC roots到这两个对象不可达,所以最终D和E还是会被当做GC的对象,上图若是采用引用计数法,则A-E五个对象都不会被回收。

             说到GC roots(GC根),在JAVA语言中,可以当做GC roots的对象有以下几种:

             1、虚拟机栈中的引用的对象。

             2、方法区中的类静态属性引用的对象。

             3、方法区中的常量引用的对象。

             4、本地方法栈中JNI的引用的对象。

             第一和第四种都是指的方法的本地变量表,第二种表达的意思比较清晰,第三种主要指的是声明为final的常量值。

             

    垃圾收集算法

     

             根搜索算法解决的是垃圾搜集的基本问题,也就是上面提到的第一个问题,也是最关键的问题,就是哪些对象可以被回收。

             不过垃圾收集显然还需要解决后两个问题,什么时候回收以及如何回收。在根搜索算法的基础上,现代虚拟机的实现当中,垃圾搜集的算法主要有三种,分别是标记-清除算法、复制算法、标记-整理算法这三种算法都扩充了根搜索算法,不过它们理解起来还是非常好理解的。

     

    结束语

     

              限于文章篇幅不要太长,本次就不具体介绍三种垃圾搜集算法了,在下一章再与各位探讨。

  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/Zyf2016/p/6337771.html
Copyright © 2011-2022 走看看