引言

从如何判定对象消亡的角度出发,垃圾收集算法可以划分为“引用计数式垃圾收集” (Reference Counting GC)和“追踪式垃圾收集”(Tracing GC)两大类,这两类也常被 称作“直接垃圾收集”和“间接垃圾收集”。

但是由于主流的 JVM 都未使用引用计数式垃圾收集,所以讨论的都是追踪式垃圾收集。

分代收集理论

所有的分代收集理论都是建设在三个假说上的。

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

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

  • 跨代引用假说:跨代引用相对于同代引 用来说仅占极少数。

基本上 主流的JVM的分代收集 都是基于这三条假说来设计的。

基于第一条假说,人所大多数的对象都是会在下一次GC进行回收,所以在GC后那些不能回收的 就会被单独归类,这样比每个都判断然后再回收的耗能要少许多。

基于第二条假说,只需要把GC剩下的那些对象进行标记(增加年龄)然后根据一些规则,放置在别的分代区间内。

分好分代区后,才可以针对不同的区采用不同的垃圾回收算法或者是垃圾回收频率。发展出了“标记-复制算法”“标记-清除算法”“标记-整理算法”等针对性的垃圾收集算法。

基于第三条假说,存在互相引用关系的两个对象,是应该倾向于同时生存或者同时消亡的。举个例子,如果某个新生代对象存在跨代引用,由于老年代对象难以消亡,该引用会使得新生代对象在收集时同样得以存活,进而在年龄增长之后晋升到老年代中,这时跨代引用也随即被消除了。

所以只需要维护一个老年代与新生代相关联的数据结构(“记忆集”,Remembered Set)这样会在GC的时候大大减少 GCRoots 的扫描与构建数量。

GC 定义

直接摘抄的原文

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

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

■老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有 CMS 收集器会有单独收集老年代的 行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老 年代的收集还是整堆收集。

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

·整堆收集(Full GC):收集整个 Java 堆和方法区的垃圾收集。

标记 - 清除

这是最早的垃圾清除算法,顾名思义就是 在GC回收的时候标记需要清楚的或者是标记需要保留的。但是也有两个很明显的缺点:

  1. 回收的效率不稳定 无法判断标记什么 如果标记的需要回收的多 标记过程就会非常的影响性能。

  2. 回收后内存地址就会分散导致没有可用的连续内存空间(引用一下原图)

标记 - 复制

这是为了解决 标记 - 清除 算法的一种解决思路。

把内存区域分割一部分 作为准备区域,在回收后直接把剩余的部分放入

这样就解决了上述的连续空间问题。

根据 更量化的研究 新生代的 98%的对象都是需要回收的 所以每次准备的备用区域并非是总区域的一半

标记 - 整理

取消掉复制的保留区域 直接进行整理就是 标记整理方法了

这样就可以节省内存空间 提高利用率