Java垃圾回收机制

来源:互联网 发布:2017淘宝避开同款教程 编辑:程序博客网 时间:2024/06/03 16:57

1. 对象已死

垃圾回收器对堆进行回收前,第一件事就是 要确定这些对象有哪些还存活着,哪些已经死去。

1.1 引用计数

给对象添加一个引用计数器,每当有一个地方引用它,计数器值就加1;当引用失效时,计数器就减1;任何时刻计数器都为0的对象就是不可再被使用的。

注意引用计数的弊端
+ 无法处理循环引用的情况,因此Java的垃圾回收没有使用这种算法
+ 引用计算器要求在每次因引用产生和消除的时候,需要一个加法和减法操作,对系统性能会有一定影响。

1.2 根搜索算法

通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象时不可用的。

1.3 四种引用

  • 强引用
    类似Object obj = new Object()这类引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
  • 软引用
    一些还有用但并非必需的对象。对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进将回收范围之中并进行第二次回收。如果回收完还是没足够的内存则抛出内存异常。
  • 弱引用
    当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
  • 虚引用
    一个对象是否有虚引用,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。唯一目的是希望能在这个对象被回收器回收时收到一个系统通知。

1.4 谁是垃圾?

需要给出一个对象的可触及性状态的定义,并规定在什么状态下,才可以安全地回收对象。+ 可触及的

从根节点开始,可以到达这个对象。
+ 可复活的
对象的引用都被释放,但是对象有可能在finalize()函数中复活。
+ 不可触及的
对象的finalize()函数被调用,并且没有复活,那么就会进入不可触及状态,不可触及的对象不可能复活,因为finalize()函数只会调用一次。

不推荐使用finalize释放资源,推荐在try-catch-finally语句中进行资源的释放。

2. 垃圾回收算法

  • 标记-清除算法

    首先标记处所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

    缺点一是标记和清除的效率都不高,另一个缺点是容易产生大量不连续的内存碎片。

  • 复制算法

    将可用内存按容量分为两块,每次使用其中的一块,当这块用完了,就将存货的对象复制到另外一块上面,然后把已使用过的内存空间一次清理掉。

    缺点是当对象存活率高的时候需要进行大量的复制操作,效率会变低。

  • 标记整理算法

    将需要回收的标记后,让所有存货的对象都向一段移动,然后清理掉端边界以外的内存。这种算法减少了内存碎片的产生。

  • 分代算法

    将Java堆分为新生代和老年代,在新生代,每次垃圾收集都发现有大批对象死去,只有少量存活,就选用复制算法。而老年代因为对象存活率高,没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来回收。

3. 垃圾回收器

3.1 新生代

  • Serial收集器

    单线程收集器,在它进行垃圾收集时,会暂停其他所有的工作线程,直到它收集结束。虚拟机运行在Client模式下的默认新生代收集器。

  • ParNew收集器

    Serial的多线程版本。Server模式下的虚拟机首选的新生代收集器。

  • Parallel Scavenge收集器

    使用复制算法的、并行的多线程新生代收集器。其目标是达到一个可控制的吞吐量。

3.2 老年代


  • Serail Old收集器
  • Parallel Old收集器
  • CMS收集器

获取最短回收停顿时间为目标的收集器。是款优秀的收集器,主要优点是并发收集、低停顿。
  • G1收集器
    基于“标记-整理”算法实现的收集器,不会产生空间碎片;可以精确地控制停顿,既能让使用者明确指定M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
  • 4. 内存分配策略

    1. 对象优先在新生代Eden中分配,当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。
    2. 需要大量连续内存空间的Java大对象直接进入老年代。避免在Eden区和Survivor区之间发生大量的内存拷贝。
    3. 长期存活的对象进入老年代。
    4. 如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。
    5. 在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代剩余空间大小,如果大于则改成一次Full GC。否则查看HandlePromotionFailure设置是否允许担保失败;如果允许,只进行Minor GC,否则Full GC。
    原创粉丝点击