Java 垃圾回收一

 

1、判断对象是否存活的算法:

<1>、引用计数法:(每个对象实例中都有一个引用计数器)当一个对象被创建的时候,该实例对象分配给一个变量,此时计数器为1。之后当其他变量引用该对象实例时,计数器+1,而当引用的变量超过生命周期,或改变为引用其他对象实例时,该对象实例计数器-1。当计数器为0的时候,则说明该对象实例没有被引用,即可以被垃圾回收掉。

缺点:当2个对象之间相互引用时,则这2个对象实例无法被回收掉,因为他们之间相互引用。

         关于缺点的理解,伪代码说明:

         {

                   O1 o1 = new O1();

                   O2 o2 = new O2();

                   o1.instance = o2;//实例O1中的一个成员变量是实例O2类型

                   o2.instance = o1;//实例O2中的一个成员变量是实例O1类型

                   o1 = null;//虽然o1 = null ,但是O2中的一个成员变量引用了O1的实例,即引用变量由 o1—>O2.instance

                   o2 = null;同理如上

         }

 

<2>、可达性分析:由定义好的GC Roots节点作为起始点开始,将所有有联系的节点全部连接到一起,最终形成类似树状的结构,此时,不在树上的节点即为可回收对象

a、优点:解决了互相引用,无法回收的问题

b、GC Roots节点对象有如下几种:

           1、方法区常量引用的对象

           2、方法区中静态成员变量引用的对象

           3、虚拟机栈中引用的对象【栈桢中的本地变量表】

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

c、二次标记机制:在可达性分析中,当被确定为可回收对象时,进行第一次标记。若该对象没有重写 finalize(),或者在重写时,没有为自己与GC Roots 树建立连接,此时进行第二次标记。二次标记结束后,当垃圾回收的时候,就会被回收掉。

注意:二次标记机制,finalize()中建立与GC Roots 树连接,一个对象只有一次机会,不会通过在finalize()中建立与GC Roots 树连接,出现一直无法回收的现象。

 

 

2、方法区垃圾回收

方法区中被回收的对象有2种:1、废弃常量;2、无用的类

<1>、废弃常量通过可达性分析 来判断

<2>、无用的类通过以下几点来判断是否回收:

             1、该类所有的实例都被回收

             2、加载该类的ClassLoader 被回收

             3、该类对应的Java.lang.Class 对象没有任何地方引用,同时无法通过反射来获取该类的方法等等。

 

 

3、垃圾回收的算法

<1>、标记清除算法

采用从 GC Roots 点开始扫描,对存活的对象进行标记,标记结束之后,再扫描整个空间中未被标记的对象进行回收。

缺点:产生内存碎片

<2>、复制回收算法 ---  解决句柄的开销和内存碎片的问题

将空间分为2部分,同样从GC Roots节点开始扫描,将存活的对象复制到另外一半中,全部扫描结束后,清空原来一半空间。

优点:不会产生内存碎片,高效

缺点:占用内存空间大

<3>、标记整理算法

标记所有存活的对象,扫描并清除整个空间中未标记的对象,在回收死亡的对象时,将存活的对象往左边空闲空间移动,建立在标记清除算法之上

优点:不会产生内存碎片

缺点:开销大

<4>、分代收集算法

目前大部分JVM使用的垃圾回收算法,核心思想是根据对象生命周期划分为若干个不同区域:新生代、老年代。新生代由于每次回收时都有大量的对象需要被回收、老年代的特点是每次垃圾回收时,只有少量对象被回收。因此,可以根据不同的区域使用不同的垃圾回收算法。

年轻代回收算法-复制回收算法(分区比例是8:1:1);老年代中回收的对象少,适合标记整理 和标记清除算法

过程:

将年轻代分为  Eden区、s0(From)区、s1(To)区。新对象产生一般在Eden区,如果Eden区满了,则将Eden区中存活的对象复制到s0区-箭头1,清空Eden区【young  GC】;如果s0区满了,则将Eden区和s0区中存活的对象复制到s1区-箭头2,清空Eden区 和 s0区【young GC】,同时将s0于s1 互换一下 -箭头2.5,确保s1区是空的。同时如果其中的对象达到了阈值(在s区中经历默认为15次young GC之后),就将达到阈值的对象放入老年代中。

如果s1区不足以存放Eden区和s0区中存活的对象则 将存活的对象直接复制到老年代 - 箭头3。如果老年代也满了,则会触发一次Full GC,频率低

如果Eden区不足以存放新建的对象,则会触发担保机制,将新建对象直接存储到老年代中。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章