JVM—垃圾收集算法和HotSpot算法实现细节
Java虚拟机(JVM)的垃圾收集机制是Java应用程序性能和稳定性的关键组成部分。JVM通过多种垃圾收集算法和技术来管理内存,确保系统高效运行。本文将深入探讨JVM的垃圾收集算法及其在HotSpot虚拟机中的实现细节。
一、垃圾收集算法
1. 标记-清除算法(Mark-Sweep)
步骤:
- 标记阶段:遍历所有可达对象并标记。
- 清除阶段:清除所有未标记的对象,释放内存。
优点:
- 简单实现。
缺点:
- 空间碎片化。
- 清除阶段的性能开销较大。
2. 标记-整理算法(Mark-Compact)
步骤:
- 标记阶段:与标记-清除算法类似,标记所有可达对象。
- 整理阶段:将所有存活对象移动到内存的一端,整理内存,释放边界外的空间。
优点:
- 避免空间碎片化。
缺点:
- 对象移动增加了额外的性能开销。
3. 复制算法(Copying)
步骤:
- 将内存分为两部分,每次只使用其中一部分。
- 在垃圾收集时,将存活的对象复制到另一部分空间。
优点:
- 高效的内存分配和回收。
- 无空间碎片化。
缺点:
- 需要额外的内存空间(两倍于实际需要)。
4. 分代收集算法(Generational Collection)
概念:
- 将堆内存分为年轻代(Young Generation)和老年代(Old Generation)。
- 年轻代进一步分为Eden区和两个Survivor区(S0和S1)。
工作机制:
- 年轻代中的对象频繁垃圾收集,存活时间短。
- 老年代中的对象存活时间长,较少进行垃圾收集。
二、HotSpot垃圾收集器
HotSpot虚拟机实现了多种垃圾收集器,每种收集器适用于不同的场景和需求。
1. Serial收集器
特点:
- 单线程工作。
- 适用于单处理器环境。
命令:
-XX:+UseSerialGC
2. Parallel收集器
特点:
- 多线程工作。
- 注重吞吐量,适用于多处理器环境。
命令:
-XX:+UseParallelGC
3. CMS收集器(Concurrent Mark-Sweep)
特点:
- 并发标记和清除。
- 低停顿时间,适用于交互响应快的应用。
命令:
-XX:+UseConcMarkSweepGC
4. G1收集器(Garbage-First)
特点:
- 面向服务端应用。
- 低停顿时间和高吞吐量的平衡。
命令:
-XX:+UseG1GC
三、垃圾收集器的工作流程
1. Serial收集器
年轻代收集:
- Eden区满:触发Minor GC,将存活对象复制到Survivor区。
老年代收集:
- 老年代满:触发Major GC或Full GC,进行标记-清除或标记-整理。
2. Parallel收集器
年轻代收集:
- 多线程并行执行Minor GC。
老年代收集:
- 多线程并行执行标记-整理。
3. CMS收集器
初始标记:
- 标记根对象,时间短。
并发标记:
- 并发标记所有可达对象。
重新标记:
- 重新标记遗漏的对象,时间短。
并发清除:
- 并发清除未标记的对象。
4. G1收集器
初始标记:
- 标记根对象,时间短。
并发标记:
- 并发标记所有可达对象。
最终标记:
- 重新标记遗漏的对象,时间短。
筛选回收:
- 根据回收收益,回收部分Region。
四、垃圾收集器的选择和调优
选择合适的垃圾收集器和调优参数,能够提高系统性能和稳定性。
1. 堆内存设置
-Xms<size> // 设置初始堆大小
-Xmx<size> // 设置最大堆大小
2. 年轻代和老年代比例
-XX:NewRatio=<ratio> // 设置年轻代与老年代的比例
-XX:SurvivorRatio=<ratio> // 设置Eden区与Survivor区的比例
3. GC日志输出
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log