在 Java 8 和 Java 11 中,垃圾回收(Garbage Collection, GC)的实现和默认策略有显著差异,尤其是在垃圾收集器的选择、性能和调优选项上。以下是两者的核心区别及使用方式:
一、Java 8 和 Java 11 的垃圾回收差异
1. 默认垃圾收集器
• Java 8
• 并行收集器(Parallel GC) 是默认的垃圾收集器,适用于多核服务器环境,强调高吞吐量(Throughput)。
• 其他可用收集器:
◦ Serial GC(单线程,适合客户端应用)
◦ CMS(Concurrent Mark-Sweep)(低延迟,已废弃)
◦ G1 GC(Garbage-First)(可选,但需手动启用)
• Java 11
• G1 GC(Garbage-First) 成为默认垃圾收集器,平衡了吞吐量和低延迟。
• 新增实验性收集器:
◦ ZGC(Z Garbage Collector)(目标暂停时间 < 10ms,适合大内存)
◦ Shenandoah GC(低延迟,与 ZGC 类似,由 Red Hat 贡献)
• CMS 和组合式收集器(如 -XX:+UseParNewGC
)被标记为废弃。
2. 关键改进
• G1 GC 的优化
• Java 11 对 G1 的混合回收(Mixed GC)和空闲内存回收(Idle GC)有显著优化,减少 Full GC 的发生。
• 低延迟收集器
• ZGC 和 Shenandoah 提供亚毫秒级暂停时间,适合对延迟敏感的应用(如实时交易系统)。
• 元空间(Metaspace)管理
• Java 11 优化了元空间的垃圾回收策略,减少元空间内存泄漏的风险。
3. 废弃和移除的功能
• Java 11 废弃
• -XX:+UseConcMarkSweepGC
(CMS)
• -XX:+UseParNewGC
(ParNew)
• Java 11 完全移除
• CMS 在后续版本中被移除(如 Java 14 中彻底删除)。
二、如何使用垃圾回收
1. 选择垃圾收集器
根据应用场景选择垃圾收集器并配置 JVM 参数:
收集器 | Java 8 启用参数 | Java 11 启用参数 | 适用场景 |
---|---|---|---|
Parallel GC | -XX:+UseParallelGC (默认) | -XX:+UseParallelGC | 高吞吐量(批处理、计算密集型) |
G1 GC | -XX:+UseG1GC | -XX:+UseG1GC (默认) | 平衡吞吐量和延迟(通用场景) |
ZGC | 不支持 | -XX:+UseZGC | 低延迟(大内存、实时系统) |
Shenandoah | 不支持 | -XX:+UseShenandoahGC | 低延迟(与 ZGC 类似) |
Serial GC | -XX:+UseSerialGC | -XX:+UseSerialGC | 单核客户端应用 |
2. 调优核心参数
• 通用参数
-Xms2g -Xmx2g # 初始和最大堆内存(建议设为相同值避免动态调整)
-XX:MaxMetaspaceSize=256m # 元空间最大大小
• Parallel GC 调优
-XX:ParallelGCThreads=4 # 并行 GC 线程数(建议等于 CPU 核心数)
-XX:MaxGCPauseMillis=200 # 目标最大暂停时间(毫秒)
• G1 GC 调优
-XX:G1HeapRegionSize=4m # Region 大小(根据堆大小调整)
-XX:MaxGCPauseMillis=150 # 目标暂停时间(默认 200ms)
-XX:InitiatingHeapOccupancyPercent=45 # 触发并发周期的堆占用率
• ZGC/Shenandoah 调优
-XX:+UseZGC -Xmx16g # 启用 ZGC 并设置堆内存
-XX:+UnlockExperimentalVMOptions # 启用实验性功能(某些版本需要)
3. 监控与分析工具
• 命令行工具
jstat -gc <pid> 1000 # 每隔 1 秒输出 GC 统计信息
jcmd <pid> GC.heap_info # 查看堆信息
• 图形化工具
• VisualVM(Java 8 自带)
• JConsole
• Eclipse Memory Analyzer (MAT)(分析堆转储文件)
• 日志分析
启用 GC 日志记录:
-Xlog:gc*:file=gc.log:time:filecount=5,filesize=100m # Java 11+ 的日志格式
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log # Java 8
三、版本升级建议
-
从 Java 8 迁移到 Java 11
• 默认垃圾收集器从 Parallel GC 改为 G1 GC,需测试 G1 在新环境下的表现。
• 如果原应用依赖 CMS,需迁移到 G1 或实验性收集器(ZGC/Shenandoah)。 -
低延迟场景
• 在 Java 11 中使用 ZGC 或 Shenandoah,但需注意:
◦ ZGC 需要较大的堆内存(建议 > 4GB)。
◦ Shenandoah 在 JDK 12 后成为正式特性,但 Java 11 中需通过 Red Hat 的构建版本使用。
四、常见问题
-
如何避免 Full GC?
• 确保堆大小合理(避免频繁扩容)。
• 使用 G1/ZGC 等现代收集器,减少停顿时间。
• 优化代码减少内存泄漏(如未关闭的资源、大对象缓存)。 -
G1 的混合回收(Mixed GC)是什么?
• G1 在并发标记后,会优先回收垃圾最多的 Region(Mixed GC 阶段),逐步减少堆占用。 -
ZGC 的局限性
• 在 Java 11 中,ZGC 不支持类卸载(需升级到 Java 15+ 解决)。
• 需要较高的 CPU 和内存资源。
五、总结
• Java 8:以 Parallel GC 为核心,适合吞吐量优先的场景。
• Java 11:默认 G1 GC,引入 ZGC/Shenandoah,适合低延迟和大内存场景。
• 调优建议:根据应用类型(吞吐量 vs 延迟)和硬件资源选择收集器,并通过日志监控和参数调优优化 GC 性能。