JAVA垃圾回收与GC浅谈

来源:互联网 发布:java jvm原理 一句话 编辑:程序博客网 时间:2024/06/05 19:35

    众所周知,java中的对象能够在"无用"的时候被GC回收,腾出空间,但是具体什么样的对象在什么样的情况下被怎样回收,其实过程还是有些小复杂,接下来就简要的谈谈这些过程:

问题一:何为"无用"对象。

1. 无任何引用的对象;根据该思想,诞生一种“引用计数法”来判断对象的存活性--

   思路:给对象添加一个引用计数器,当引用计数器为0的时候,代表对象可回收;

 缺点:无法解决循环引用,整个对象无用问题;

 因此,该思想与方法虽然也有一些虚拟机在用,但是比较少见。

2.为了克服“引用计数法”所带来的缺陷,提出了“根搜索算法(GC Root)”;

 思路:若一个对象,或者一些列对象到GC Root没有引用链接,则算作可回收已死对象;

 GC Root:总的来说,就是一个对象的初始引用,不包括其他内部的二次引用;具体有如下几种情况--     

    a.虚拟机栈(栈帧中本地变量表中)的引用;

    b.本地方法栈中JNI的引用;

    c.方法区中常量的引用;

    d.方法区中静态变量的引用;

    特别注意:不包括堆中对象的所持有的实例变量;

    例如:

class A{public B b = null;}class B{}public void case1(){B b1 = new B();A a1 = new A();//A中的实例变量b指向了对象ba1.b = b1;}
    在上面的例子中,a1,b1都是方法case1()中的本地变量,因此都存在与java虚拟机栈栈帧中的本地变量表中,此刻,对象b1和a1的都有到GC ROOT的引用链,其中a1的GC ROOT是变量a1,b1的GC ROOT是变量b1和a1;这时,如果令b1=null;这时,对象b1将失去b1这个变量,即GC ROOT,但是,该对象还是有一个引用在身,即a1.b = b1;而a1本身又是有GC ROOT的存货对象,因此b1的引用链任然可以延伸至a1变量,即b1对象任然有GC ROOT; 但如果此刻令 a1 = null;则虽然b1对象还是有引用在身,即a1.b=b1,但是该引用只是堆中的实例变量的引用,不可作为GC ROOT,因此,此刻b1找不到任何GC ROOT引用链了,即b1为“无用对象”,当然此刻a1也为无用对象。

    优点:解决了循环引用不可回收问题;因此也被作为目前最为广泛应用的判断对象存货的方法。


补充:“无用类”;

              方法区中的类信息同样也会被GC回收处理,一个类无用,需要满足以下3个条件:            

              A.该类所有实例(对象)均已经回收;

              B.加载该类的ClassLoader已经回收;

              C.该类对应Class对象没有被引用;


问题二:怎样回收对象。

        当虚拟机知道了哪些对象该被回收后,就该采取一定措施实施回收了,主要有-标记清除法,复制回收法(Eden,survivor),

标记-整理算法,分代收集算法;

  1.标记清除法;如图1,是运用该方法回收对象的依次完整GC过程;


                                     图1

  2.复制回收法;

     该方法在分配内存的时候,就将内存进行划分,分成8:1:1的比例,其中最大的一块为Eden,两块较小的为Survivor;

     在分配的时候,都是用Eden和一块Survivor,进行GC后仍然存活的对象,移动到另一块Survivor,然后把第一块Survivor和Eden

     里的对象都清空;这里,新分配的对象都是在Eden区域,但是GC覆盖面是Eden和一块Survivor,被判定为存活的对象,通通复制到另一块

     Survivor,然后清空其余两块区域内的对象;这时,两块survivor的角色互换了,空的一块作为下一轮GC接收复制存活的对象。

     特点:由于短期的活动内存区较大,而长期的内存保存区域较小,所以适合新生代,活动频繁的算法。

  3.标记-整理算法

     与标记清理法过程差不多,标记过程一致,但是最后清理对象的时候,不是直接清理,而是把未标记的对象往一侧移动,然后清

     理掉末端的其他所有标记的对象;

     特点:当存活对象较为多的时候,则移动间隔不是很多,因此采用该方法对于老年代比较适合。

  4.分代收集算法

     综合上诉各种方法特点,将java堆分为新生代和老年代,新生代-对象朝生晚死,生命周期短的区域;老年代-对象一般存活较久

     生命周期较大;

     对于新生代采用复制回收法,老年代采用标记-清理或者标记整理法。


问题三:对象如何分配。

     对象分配大致原则如下图2:



 图2
    

                               (注:空间担保中,是让survivor无法容纳的对象进入老年代,能容纳的还是容纳在survivor) 
    主要遵循以下原则:

     1. 优先分配新生代->Eden->不够分->minGC,复制回收法转Survivor->无法回收->转老年代->新对象分配于Eden

         MinorGC-新生代GCMajorGC/FullGC老年代GC

     2. 大对象直接分配老年代,避免复制回收法大量频繁复制;

     3. 新生代中(Survivor存活区)年龄超过阀值,进入老年代(一次MinorGC后长一岁,第一次GC为一岁)

     4. 新生代中Survivor中的相同年龄的对象大小和超过Survivor的一半,则该年龄对象进入老年代;

    

  

       

0 0
原创粉丝点击