Java 8 和 Java 11 在垃圾回收(GC)上的主要区别体现在默认垃圾收集器的变化、新增收集器的引入以及算法优化上。
以下是详细对比:
1. 默认垃圾收集器的变化
Java 8
默认垃圾收集器:Parallel Scavenge GC(新生代) + Parallel Old GC(老年代)。
Parallel Scavenge GC 是一种并行垃圾收集器,主要目标是高吞吐量。
Parallel Old GC 是老年代的并行标记-清除垃圾收集器。
Java 11
默认垃圾收集器:G1(Garbage First)GC。
G1 从 Java 9 开始成为默认收集器,Java 11 延续这一配置。
G1 适用于延迟敏感型应用,能够显著减少全局停顿时间(STW)。
2. 新增垃圾收集器
Java 8
支持的收集器包括:Serial GC、Parallel GC、CMS(Concurrent Mark-Sweep)GC,但没有引入新的垃圾收集器。
Java 11
新增 ZGC(Z Garbage Collector):
ZGC 专为低延迟场景设计,暂停时间通常在几毫秒内,即使在大堆内存(TB 级)下也能保持低延迟。
提供高吞吐量与可伸缩性。
3. GC 算法优化
Java 8:基于简单的可达性分析
可达性分析:
标记活跃对象,回收不可达对象。
通过从根对象(GC Roots)开始的直接或间接引用判断对象的存活状态。
Java 11:引入三色标记算法(G1 GC)
三色标记算法:
使用三种颜色(白、灰、黑)标记对象状态:
白色:未被标记为可达,可能是垃圾。
灰色:已被访问,但子对象尚未处理。
黑色:已访问并处理完子对象。
动态并发标记,显著减少 Stop-The-World(STW)的时间。
4. 内存分配策略
Java 8:固定内存分区
堆分为 新生代(Young Generation) 和 老年代(Old Generation),比例固定。
新生代进一步划分为 Eden 区和 Survivor 区,使用固定的内存分配策略。
Java 11:G1 自适应分区
堆被划分为多个大小相同的区域(Region)。
动态分配内存:
G1 根据堆的使用情况动态调整 Eden、Survivor 和 Old 的区域比例。
区域的动态调整提高了内存利用率和 GC 效率。
5. 停顿时间优化
Java 8
Parallel GC 强调高吞吐量,但在 Full GC 时会发生较长的全局暂停。
CMS 收集器虽然减少了 Full GC,但在老年代空间不足时仍可能触发长时间的 STW。
Java 11
G1 提供了可预测的停顿时间,允许用户通过参数设置目标延迟时间:
参数:
-XX:MaxGCPauseMillis=<n>
。GC 优化路径根据目标延迟调整回收策略。
引入 ZGC 后,进一步优化了大堆内存下的低延迟需求,暂停时间通常低于 10ms。
6. 总结对比
推荐选择
Java 8 的默认 GC 适合批量处理任务,强调吞吐量。
Java 11 的 G1 和 ZGC 更适合延迟敏感的应用,尤其是需要大堆内存的场景。