目录
2. Parallel Scavenge/ Parallel Old收集器
常见的垃圾回收算法
标记复制算法
将内存分为相等的两块,每次仅使用其中的一块;垃圾回收时,标记存活的对象,将存活的对象复制到另一块区域中,并清理当前区域。(根据两块的逻辑可以判断出这是针对年轻代的一种算法)
问题:
标记清除算法
算法分为“标记”和“清除”阶段:标记存活的对象, 统一回收所有未被标记的对象(一般选择这种);也可以反过来,标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象 。它是最基础的收集算法,比较简单,但是会带来
两个明显的问题:
1. 效率问题 (如果需要标记的对象太多,效率不高)
2. 空间问题(标记清除后会产生大量不连续的碎片)
标记整理算法
根据老年代的特点特出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存,优化了“标记-清除”算法的问题。
垃圾回收器
没有完美的垃圾回收器,只能很具具体场景选择具体的垃圾回收器。
1. Serial收集器
- 特点:单线程,Stop-The-World,直到它结束
- 算法:复制算法(年轻代) + 标记-整理(老年代)
- 适用场景:
- 客户端应用
- 小内存(几十MB到一两百MB)
- 单核CPU环境
- 优点:简单高效,没有线程交互开销
- 缺点:停顿时间长
- 参数:-XX:+UseSerialGC
-XX:+UseSerialGC -XX:+UseSerialOldGC
2. Parallel Scavenge/ Parallel Old收集器
- 特点:多线程并行,关注吞吐量
- 算法:复制算法 + 标记-整理
- 适用场景:
- 后台计算密集型应用
- 科学计算、批处理任务
- 不关注单次停顿时间,关注整体吞吐
- 优点:吞吐量高,CPU利用率高
- 缺点:停顿时间不可控,对延迟不敏感
- 参数:
- -XX:+UseParallelGC
- -XX:+UseParallelOldGC
- -XX:ParallelGCThreads=4
- -XX:MaxGCPauseMillis=100
其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略,甚至STW等等)和Serial收集器类似。默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。
在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器)。
3. ParNew + CMS
ParNew ,主要针对年轻代,ParNew收集器其实跟Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用
- 特点:Serial的多线程版本
- 算法:复制算法
- 作用:与CMS配合使用
CMS
Concurrent Mark Sweep,主要针对老年代
- 特点:并发收集,减少停顿时间;在 JDK 14 及之后的版本中,你无法再使用 CMS 垃圾回收器
- 算法:标记-清除
- 适用场景:
- Web服务器、GUI应用
- 对响应时间敏感的系统
- 优点:低停顿,用户体验好
- 缺点:
- 产生内存碎片
- CPU资源敏感(会和服务抢资源)
- 并发失败时退化为Serial Old
- 执行过程中的不确定性,会存在上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况,特别是在并发标记和并发清理阶段会出现,一边回收,系统一边运行,也许没回收完就再次触发full gc,也就是"concurrentmode failure",此时会进入stop the world,用serial old垃圾收集器来回收
- 参数:-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
为什么CMS停顿时间短?
CMS GC: 初始标记(短暂STW) → 并发标记 → 重新标记(短暂STW) → 并发清除
将GC工作分摊到多个阶段,只有初始标记和重新标记需要短暂STW
并发标记和并发清除阶段与用户线程一起运行,不停止应用
使用卡表和增量更新等技术,减少重新标记阶段的工作量
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作(Parallel收集器工作期间必须STW)
G1 (Garbage First)
- 特点:面向服务端,可预测的停顿时间模型
- 算法:标记-整理 + 分区算法
- 内存布局:将堆划分为多个Region(1MB~32MB)
- 适用场景:
- 大内存应用(6GB+)
- 要求停顿时间可控
- JDK9+ 的默认选择
- 优点:
- 停顿时间可控
- 整体吞吐量与Parallel相当
- 有效处理大内存
- 缺点:
- 内存占用稍高,堆内存 < 4GB时,G1优势不明显
- JDK6/7中不够成熟
- 追求极致吞吐时,Parallel更优
- 需要亚毫秒级停顿时,ZGC更合适
- 参数:
- -XX:+UseG1GC
- -XX:MaxGCPauseMillis=150
- -XX:G1HeapRegionSize=16m
Q: 为什么G1能替代CMS?
A: "G1解决了CMS的内存碎片问题,同时提供了可预测的停顿时间,在大内存场景下表现更好"
ZGC (The Z Garbage Collector)
- 特点:超低停顿(<10ms),不分代
- 算法:并发标记-整理
- 适用场景:
- 超大堆内存(TB级别)
- 极致低延迟要求
- 新架构应用
- 优点:
- 停顿时间极短且与堆大小无关
- 吞吐量损失小
- 缺点:JDK15才正式生产可用,兼容性要求高
- 参数:
- -XX:+UseZGC
- -Xmx16g -Xms16g
- -XX:SoftMaxHeapSize=14g
- -XX:MaxGCPauseMillis=10
如何选择JVM垃圾回收器
有多个维度需要注意:
- 应用类型:Web服务、批处理、客户端?
- 堆内存大小:小(<2G)、中(2-8G)、大(>8G)?
- 停顿要求:可容忍秒级、百毫秒级、十毫秒级?
- 吞吐要求:最大化吞吐量还是保证响应时间?
- JDK版本:JDK8还是JDK11+?
小内存或客户端 → Serial
批处理重吞吐 → Parallel Scavenge + Parallel Old
JDK8 Web应用低延迟 → ParNew + CMS
JDK9+ 现代应用 → G1 (默认)
超大堆极致低延迟 → ZGC/Shenandoah
101

被折叠的 条评论
为什么被折叠?



