主要算法
标记-清除算法(Mark-Sweep)
标记-清除算法是最基础的垃圾回收算法,分为标记和清除两个阶段。标记阶段遍历所有可达对象并标记,清除阶段回收未被标记的对象内存。适用于内存碎片不敏感的场景,如早期Java虚拟机。缺点是会产生内存碎片,可能引发频繁的GC。
复制算法(Copying)
复制算法将内存分为两块,每次只使用一块。当一块内存用完时,将存活对象复制到另一块,并清空当前块。适用于对象存活率低的场景,如新生代垃圾回收。优点是高效无碎片,但内存利用率仅50%。
标记-整理算法(Mark-Compact)
标记-整理算法在标记-清除的基础上增加了整理阶段,将存活对象向一端移动,然后清理边界外的内存。适用于老年代回收,避免内存碎片问题。缺点是移动对象成本高,适合对象存活率高的场景。
分代收集算法(Generational)
分代收集算法根据对象生命周期将堆分为新生代和老年代,针对不同代采用不同算法(如新生代用复制算法,老年代用标记-整理)。适用于大多数现代语言运行时(如Java、.NET),能平衡停顿时间和吞吐量。
垃圾收集器类型
串行收集器(Serial GC)
- 特点:单线程STW(Stop-The-World),简单高效。
- 适用场景:客户端程序或小内存服务端,但停顿时间较长。
通过以下JVM参数启用:
-XX:+UseSerialGC
并行收集器(Parallel GC)
- 特点:多线程并行执行Minor和Full GC,吞吐量优先。
- 适用场景:计算密集型任务(默认JDK8的收集器)。
启用参数:
-XX:+UseParallelGC
调整线程数和目标停顿时间:
-XX:ParallelGCThreads=N
-XX:MaxGCPauseMillis=time_ms
并发标记清除收集器(CMS)
- 目标:减少Full GC停顿时间。(JDK5引入,JDK9弃用,JDK14删除)
- 流程:
- 初始标记(STW):标记根直接关联对象。
- 并发标记:标记所有可达对象(与用户线程并行)。
- 重新标记(STW):修正并发期间的变动。
- 并发清除:清理垃圾(与用户线程并行)。
- 缺点:内存碎片、CPU资源竞争。启用参数:
-XX:+UseConcMarkSweepGC
调整并发阶段线程数和出发阈值
-XX:ConcGCThreads=N
-XX:CMSInitiatingOccupancyFraction=percent
G1收集器(Garbage-First)
- 区域化堆(Region):将堆划分为多个等大小Region(每个1MB~32MB),优先回收垃圾最多的Region。
- 回收策略:
- 预测停顿时间:优先回收垃圾比例高的Region(Garbage-First)。
- Mixed GC:同时回收新生代和老年代的Region。当老年代空间达到阈值会触发
- Young GC:当新生代的空间不足时,G1触发Young GC回收新生代空间 Young GC主要是对Eden区进行GC,它在Eden空间耗尽时触发,基于分代回收思想和复制算法,每次Young GC都会选定所有新生代的Region,同时计算下次Young GC所需的Eden区和Survivor区的空间,动态调整新生代所占Region个数来控制Young GC开销
- 优点:可预测停顿时间(默认目标200ms)。
JDK9后成为默认GC,能预测停顿时间。
-XX:+UseG1GC
设置最大停顿时间和区域大小
-XX:MaxGCPauseMillis=time_ms
-XX:G1HeapRegionSize=size_mb
- 阶段:
- 初始标记(Initial Mark):标记GC Roots直接关联对象(STW)。
- 并发标记(Concurrent Mark):识别存活对象(并发)。
- 最终标记(Final Mark):处理剩余SATB(Snapshot-At-The-Beginning)记录(STW)。
- 筛选回收(Evacuation):选择Region进行回收(STW)。
ZGC收集器(Z Garbage Collector)
- 目标:亚毫秒级停顿(<10ms),支持TB级堆,如云原生应用。
- 关键技术:
- 染色指针:使用指针元数据跟踪对象状态。
- 并发压缩:无需STW即可移动对象。
- 适用场景:低延迟、大内存应用(
-XX:+UseZGC
)。
JDK15后成为生产特性,需要64位系统支持。
# ZGC
-XX:+UseZGC
Shenandoah收集器
Shenandoah算法通过转发指针和读屏障实现并发整理,停顿时间与堆大小无关。适用于需要低延迟且堆内存较大的场景,与ZGC类似但实现方式不同。JDK12后成为生产特性。
# Shenandoah
-XX:+UseShenandoahGC