
粉丝提问:
Java 的垃圾回收器(GC)有什么作用?G1、ZGC 和 Shenandoah 有什么区别?如何根据场景选择最适合的 GC?
本文将通过丰富的代码示例深入讲解垃圾回收(Garbage Collection)的核心概念,比较 G1、ZGC 与 Shenandoah 的特性,提供调优技巧,助你选择最适合的 GC。
垃圾回收(GC)是 Java 虚拟机(JVM)自动内存管理的一部分,用于回收不再使用的对象内存。
public class GCDemo {
public static void main(String[] args) {
// 创建一个对象
GCDemo demo = new GCDemo();
System.out.println("对象已创建:" + demo);
// 将引用置为 null,便于回收
demo = null;
// 强制调用垃圾回收(仅建议测试使用)
System.gc();
System.out.println("垃圾回收已触发");
}
@Override
protected void finalize() throws Throwable {
System.out.println("对象被回收:" + this);
}
}作者名片 ✍️
Java 提供多种垃圾回收器,每种都有其特点和适用场景。
public class G1GCDemo {
public static void main(String[] args) {
System.out.println("G1 GC 示例启动");
for (int i = 0; i < 1_000_000; i++) {
byte[] data = new byte[1024 * 1024]; // 创建大对象
}
System.out.println("G1 GC 示例结束");
}
}启动参数:
java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 G1GCDemopublic class ZGCDemo {
public static void main(String[] args) {
System.out.println("ZGC 示例启动");
for (int i = 0; i < 1_000_000; i++) {
byte[] data = new byte[1024 * 1024]; // 创建大对象
}
System.out.println("ZGC 示例结束");
}
}启动参数:
java -XX:+UseZGC -Xmx16G ZGCDemopublic class ShenandoahGCDemo {
public static void main(String[] args) {
System.out.println("Shenandoah GC 示例启动");
for (int i = 0; i < 1_000_000; i++) {
byte[] data = new byte[1024 * 1024]; // 创建大对象
}
System.out.println("Shenandoah GC 示例结束");
}
}启动参数:
java -XX:+UseShenandoahGC ShenandoahGCDemo通过 -XX:MaxGCPauseMillis 设置目标暂停时间。
java -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -Xmx4G G1GCDemo使用 GC 日志分析回收行为。
java -Xlog:gc* -XX:+UseG1GC G1GCDemo[0.048s][info][gc] GC pause (G1 Evacuation Pause) (young)
[0.050s][info][gc] GC pause (G1 Mixed) (to-space exhausted)通过 -Xmx 设置堆内存上限,优化内存分配。
java -XX:+UseZGC -Xmx8G ZGCDemo作者名片 ✍️
特性 | G1 | ZGC | Shenandoah |
|---|---|---|---|
暂停时间 | 可控(用户设置目标) | 极低(10ms 以下) | 较低(10ms~100ms) |
并发回收 | 部分并发 | 几乎全并发 | 大部分并发 |
内存大小支持 | 大型内存(4GB~16TB) | 超大内存(16TB) | 中大型内存(1GB~10TB) |
适用场景 | 在线系统 | 实时性要求高的系统 | 混合负载系统 |
性能稳定性 | 较高 | 极高 | 较高 |
-XX:MaxGCPauseMillis 设置目标暂停时间。-XX:MaxGCPauseMillis=<time>:设置最大暂停时间(如 100ms)。-XX:InitiatingHeapOccupancyPercent=<percent>:设置老年代启动垃圾回收的阈值。java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:InitiatingHeapOccupancyPercent=45 MyApp-XX:+UseZGC:启用 ZGC。-Xmx<size>:设置最大堆内存大小。java -XX:+UseZGC -Xmx16G MyAppA:使用以下工具:
-Xlog:gc* 启用详细 GC 日志。A:ZGC 几乎所有回收操作都在并发完成,避免了全停顿。
A:G1 的分区式收集和暂停时间目标设计,使其更适合延迟敏感的场景。
选择垃圾回收器的关键点: