1. 垃圾收集算法
1.1 对象分代收集理论
- 垃圾收集器大都数都遵循“分代收集”理论,主要简历在两个分代假说上:
- 弱分代假说:绝大多数对象都是朝生夕灭的。
- 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。
- 跨代引用假说:跨代引用相对于同代来说仅占极少数。
- 这几个分代假说共同奠定了多款常用的垃圾收集器一致的设计原则(例如 HotSpot)。收集器应该将堆划分出不同的区域,然后将回收对象依据其熬过垃圾收集过程的次数分配到不同的区域中存储。
- 如果一个区域中大多数对象都是难以熬过垃圾收集过程的话,那么把他们集中放在一起,每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象,就能以低代价回收到大量的空间。(新生代)
- 如果剩下的都是难以回收的对象,那么把他们集中放在一块虚拟机可以使用较低的频率来回收这个区域,这就同时兼顾了垃圾收集的时间开销和内存的空间的有效利用。(老年代)
- 如果存在跨代引用的情况下,由于老年代难以回收,新生代对象也会难以回收,进而在年龄增长之后新生对象也进入到老年代,这时,跨代引用也会随即被消除。
1.1.1 GC 名词解释
- 部分收集(Partial GC):指目标不是完整收集整个堆
- 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
- 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。
- 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
- 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
标记-清除算法(Mark-Sweep) - 由名字也可以看出来,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。
- 它是最基础的收集算法,后续的收集算法大多都是以标记-清除算法为基础,对它的缺点进行改进而得到的。它的主要缺点有两个
- 执行效率不稳定:如果 Java 堆中包含大量对象,而且其中大部分是需要回收的,就需要进行大量标记和清除的动作,会随着对象数量增长而降低。
- 内存空间碎片化问题:清除之后可能会有大量不连续的内存碎片,空间碎片太多可能会导致程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
- 图式:
1.2 标记-复制算法(Semispace Copying)
-
标记-复制算法常被称为复制算法。为了解决标记-清除算法面对大量可回收对象时执行效率低的问题,将将内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用我拿了,就江海存活着的对象复制到另一块上面,然后再把使用过的全部清理掉。
- 如果内存中大多数对象都是存活的,这种算法将会产生大量的内存间复制的开销。
- 如果多数对象都是可回收的情况,算法需要复制的是少数存活的对象,由于每次都是针对半个区进行内存回收,分配时也就不用考虑有空间碎片化的复杂情况,只要移动堆顶指针,按顺序分配即可。代价就是将可用内存缩小为原来的一半。
-
图示
-
HotSpot 使用了一种更优化的半区复制分代策略(Appel 式回收)。Appel 式回收的具体做法是把新生代分为一块较大的 Eden 空间和两块较小的Survivor 空间,每次分配内存只使用 Eden 和其中一块Survivor。发生 GC 时,将 Eden 和Survivor 中仍然存活的对象一次性复制到另外一块Survivor 空间上,然后直接清理 Eden 和已用过的那块Survivor 区。
- Hotspot 虚拟机默认 Eden、Survivor1、Survivo2 的大小比例为 8:1:1,每次新生代中可用的内存空间为整个新生代容量的 90(Eden 区与Survivor 其中一个区)。
- 当Survivor 空间不足以容纳一次 GC 之后存活的对象,就会直接进入老年代。
1.3 标记-整理算法(Mark-Compact)
- 标记-复制算法在对象存活率较高时要进行较多的复制操作,效率将会降低。一旦存活对象较多时需要额外的内存空间进行分配担保,所以老年代一般不直接选用这种算法。
- 标记-整理算法的标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。
- 如果移动存活对象,尤其在老年代这种每次回收都有大量对象存活区域,移动存活对象并更新所有引用这些对象的地方将会是一种极为负重的操作,而且这种对象移动操作必须全程暂停用户应用线程才能进行。但如果像“标记-清除”算法那样完全不考虑移动和整理存活对象,在堆中的存活对象导致的空间碎片化问题。
- 图式:
评论前必须登录!
注册