美文网首页
jvm的垃圾回收策略

jvm的垃圾回收策略

作者: lurenjia | 来源:发表于2018-04-06 15:03 被阅读0次

    一. 如何判断对象是否存活
    1. 引用计数法。 给对象添加一个计数器,每当一个地方引用它的时候极速器加1,当引用失效就减1,任何时刻计数器为0表明该对象不会再被使用。 实际上引用计数法的实现简单,效率也高。但是主流的JVM都没有使用它,因为他很难解决对象之间的循环引用问题。 比如说A的属性中引用了B,B的属性中引用了A,除此之外在没有别的对象引用,这两个对象也不可能在被访问,但是由于他们两个循环引用,导致计数不为0,所以不能被GC。
    2. 可达性分析法。 这个算法的基本思路是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜寻,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何路径相连时,则证明此对象是不可用的。 可以作为GC Roots的对象包括下面几种:
    <1> 虚拟机栈中引用的对象
    <2>类静态属性引用的对象
    <3>方法区中常量引用的对象
    <4> 本地方法栈中JNI引用的对象

    二 垃圾收集算法

    1. 标记清除发。该算法分为标记-清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收。这个种算法主要有两个不足,一个是效率问题,标记和清除的效率都不高,另外一个是标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致程序运行的时候需要分配较大的对象的时候,无法找到足够的连续内存而再一次触发GC。
    2. 复制算法。 这种算法是依据上面的标记清除算法改进而来。 他将可用内存划分为相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存在的对象复制到另外一块上,然后把已使用的内存一次清理掉。这样就是对整个半块内存就行内存回收,不用考虑内内存碎片的问题了。这种方法实现简单,效率也高。但是内存只用一半,代价未免太高了点。
      实际上在商业虚拟机中又会分为老年代和新生代,新生代大多会用这种复制法,但是也不是将内存分为两部分。而是将新生代的分为3个部分,一块较大的Eden空间和两块较小的Surevior空间,比例大概是8:1:1.因为有专门的研究表明,新生代中的对象98%的是朝生夕死的。所以实际内存分配的时候会使用Eden和一个Surevior,内存回收的时候将活着的对象复制到另外一个SUrevior中,这样浪费的内存就少了。但是极少数的情况下可能需要复制的内存会超过Surevior,这个时候就会使用老年代的内存就行担保,就直接进入了老年代。 事实上新生代每一次GC存活下来的对象的年龄都会加1,当这个对象的年龄超过某一个值得时候,默认是15,也会进入老年代。
    3. 标记整理法。 复制算法如果对象存活率较高的时候就要进行多次复制。,效率会变低。 根据老年代的特点提出了另外一种算法,标记整理法。 标记跟前面的一样,但是后续不是清理,而是让存活的对象都向一段移动,然后在清理移动之后的内存。
      所以现在的商业虚拟机大多都会采用复制和标记整理算法来实现垃圾回收。新生代采用复制算法,老年代采用标记整理算法。

    **本文大多数来至《深入理解Java虚拟机》

    相关文章

      网友评论

          本文标题:jvm的垃圾回收策略

          本文链接:https://www.haomeiwen.com/subject/vpkshftx.html