JVM原理(四):JVM垃圾收集算法与分代收集理论

发布于:2024-07-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

从如何判定消亡的角度出发,垃圾收集算法可以划分为“引用计数式垃圾收集”和“追踪式垃圾收集”两大类。

本文主要介绍的是追踪式垃圾收集

1. 分代收集理论

当代垃圾收集器大多遵循“分代收集”的理论进行设计,它建立在两个假说之上:

  • 弱分代假说:绝大多数对象都是朝生夕灭的。

  • 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。

以上两个假说共同奠定多款垃圾收集器的设计原则:收集器应将Java堆划分出不同的区域,然后将回收对象依据其年龄分配到不同的区域中存储。

回收类型划分:将Java堆划分出不同区域之后,垃圾收集器每次只回收其中某一个或某部分区域——因而才有“Minor GC”、“Major GC”、“Full GC”这样的回收类型划分。同时也发展出“标记-复制算法”,“标记-清除算法”、“标记-整理算法”等针对性的收集算法。

第三个假说的添加:

  • 跨代引用假说:跨代引用相对于同代引用来说仅占极少数。存在互相引用关系的两个对象,是应该倾向于同时生存或同时消亡。

垃圾收集器名词:

  • 部分收集(Partial GC):指目标不是完整手机整个Java堆的垃圾收集,其中又分为

    • 新生代收集(Minor GC):指目标只是新生代的垃圾收集。

    • 老年代收集(Major GC):指目标只是老年代的垃圾收集。。目前只有CMS收集器会有单独收集老年代的行为。

    • 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。

  • 整堆收集:收集整个Java堆和方法去的垃圾收集。

2. 标记-清除算法

标签:最早出现也是最基础的垃圾收集算法。

过程:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。也可以反过来。


优点:

缺点:

  • 执行效率不稳定。

  • 产生空间碎片化问题,对清除后的对象分配内存不利。

3. 标记-复制算法

标签:为了解决标记-清除算法面对大量可回收对象时执行效率低的问题。

过程:将内存划分为两块相等的大小,每次只使用其中的一块。进行垃圾收集时,将存活的对象复制到另外一块,再把使用的内存块清理掉。


优点:实现简单,运行高效

缺点:代价是将可用内存空间缩小一半。


附录

现在商业Java虚拟机大多采用这种算法进行收集,IBM曾进行过统计,新生代的百分之98的对象都熬不多第一次收集,因此不必用1:1比例来划分空间。


理论进阶(HotSpot使用的)

“Appel 回收”:Appel式回收把新生代分为一块较大的Eden空间和两块较小的Survivor空间,每次分配内存只使用Eden和其中一块Survivor。

过程:发生垃圾收集时,将Eden和Survivor中仍存活的对象一次性复制到另外一块Survivor上,然后清理Eden和已使用的Survivor。当Survivor空间不足以容纳一次Minor GC之后的存活对象,就需要老年代进行分担。

4. 标记-整理算法

标签:在对象存活率较高时就要进行较多的复制操作,效率会更低,对标记-清除算法的一种改进。

过程:发生垃圾收集时,将存活的对象标记,然后清除回收未标记的对象,然后再进行排序。


优点:合理利用空间,内存空间划分规整。

缺点:在进行整理的时候,会暂停对象的分配,我们称之为“stop the world”。