在java中,垃圾回收(gc)是重要的过程,用于管理内存,回收不被使用的对象,垃圾回收主要针对的是内存结构中的堆内存进行回收,内存结构和回收算法请参考java内存结构及垃圾回收算法介绍
垃圾回收器的介绍
垃圾回收器 | 优点 | 缺点 | 针对 | 特性 | 常见组合方式 |
Serial | 简单高效 | 单线程导致停顿较长 | 新生代 | 单线程,使用标记-复制算法,适合客户端模式 | Serial(新生代) + Serial Old(老年代) |
ParNew | 多线程,与CMS配合效果较好 | 停顿较长,可能影响服务质量 | 新生代 | 多线程,使用标记-复制算法,CMS的新生代替代者,可与CMS搭配 | ParNew(新生代) + CMS(老年代) |
Parallel | 多线程,适合高吞吐量 | 停顿较长,可能影响服务质量 | 新生代 | 多线程,并行垃圾收集,吞吐量优先 | Parallel Scavenge(新生代) + Serial Old(老年代) |
CMS | 并发收集,短暂停顿,适合响应敏感应用 | 内存碎片,吞吐量相对较低 | 老年代 | 并发收集,标记-清除算法,减少停顿时间 | ParNew(新生代) + CMS(老年代) |
G1 | 并发收集,短暂停顿,高吞吐量 | 初始标记和最终标记阶段的停顿较长 | 新生代和老年代 | 区域任意收集,基于标记-整理算法,根据堆内存划分为多个区域,按照区域优先级执行垃圾回收,适用于大堆内存场景 | G1(新生代和老年代) |
ZGC | 极短暂停时间,适用于超大堆内存 | 相比G1的吞吐量略低 | 新生代和老年代 | 并发收集,标记-整理算法,目标是将停顿时间限制在10ms以内,适用于大堆内存场景 | ZGC(新生代和老年代) |
吞吐量
吞吐量是处理器用于运行用户代码的时间与处理器总消耗时间的比值。Parallel Scavenge收集器的目标是达到一个可控制的吞吐量,即最大限度地提高虚拟机的运算能力
Serial收集器
Serial收集器是java虚拟机最早的新生代收集器,它采用单线程工作方式,也叫"串行垃圾回收器"
Serial GC 是一种基于标记-复制算法的垃圾回收器。
它通过暂停应用程序的所有线程来执行垃圾回收操作,因此也被称为“Stop-The-World”垃圾回收器
在垃圾回收过程中,Serial GC 使用单个线程来扫描和回收堆内存中的对象,这样可以简化实现并减少系统开销,但也导致了较长的停顿时间。由于其简单性和低系统开销,Serial GC 通常适用于小型应用和开发环境。
Parallel 收集器
Parallel GC 是 Serial GC 的并行版本,它利用多个线程来并行执行垃圾回收操作,以提高回收效率。Parallel GC 适用于多核处理器和需要高吞吐量的大型应用场景,那些后台运算而不需要太多与用户交互的任务。与 Serial GC 类似,Parallel GC 也使用“Stop-The-World”机制进行垃圾回收,因此会造成较长的停顿时间
ParNew 收集器
ParNew收集器是HotSpot虚拟机中的新生代垃圾收集器,它是Serial收集器的多线程并行版本
与CMS收集器配合
ParNew收集器常与CMS收集器(Concurrent Mark-Sweep)搭配使用。ParNew负责新生代的垃圾收集,而CMS负责老年代的并发收集。这种搭配在特定场景下能够提供较好的垃圾收集性能和较低的停顿时间
更先进的垃圾收集器如G1(Garbage First)的出现,逐渐取代了ParNew收集器。G1收集器是一种面向全堆的垃圾收集器,不需要其他新生代收集器的配合。从JDK 9开始,ParNew收集器和CMS收集器已经不再是官方推荐的垃圾收集器解决方案
CMS收集器
CMS收集器是一种旨在最小化垃圾回收停顿时间的Java垃圾收集器。它适用于对服务端应用程序的响应时间要求较高的场景,特别是那些运行在互联网网站或基于浏览器的B/S系统的服务端,采用标记-清除算法进行老年代垃圾回收,弊端就是产生内存碎片
CMS收集器的优点
耗时最长的并发标记和并发清除阶段垃圾收集器线程可以与用户线程一起工作,使得CMS收集器的内存回收过程与用户线程并发执行,从而降低停顿时间
CMS收集器的缺点
- 对处理器资源敏感:CMS收集器占用一部分线程(或处理器计算能力),这可能导致应用程序的总吞吐量下降,特别是在处理器核心数较少的情况下
- 无法处理浮动垃圾:由于并发标记和清除期间仍会有新的垃圾对象产生,这些垃圾对象无法在当前收集中处理,而必须留待下一次垃圾收集时再清理,称为"浮动垃圾"。这可能导致"Concurrent Mode Failure"失败,并触发另一次完全"Stop The World"的Full GC
- 空间碎片问题:CMS收集器使用标记-清除算法,回收结束时会产生大量空间碎片。这可能导致大对象分配困难,而不得不提前触发一次Full GC
为了解决这些问题,CMS收集器提供了一些参数进行配置,例如可以调整触发垃圾收集的阈值、启用内存碎片的合并整理过程等。然而,尽管CMS收集器在过去是一款优秀的选择,但自从JDK 9开始,它已被标记为废弃
G1收集器
G1收集器是Java垃圾收集器技术的重要进展,它开创了面向局部收集的设计思路和基于Region的内存布局形式。G1的目标是实现可预测的停顿时间模型,使其成为一款适用于服务端应用的垃圾收集器
G1收集器的特点
基于Region的内存布局:G1将Java堆划分为多个大小相等的Region,每个Region可以扮演不同角色,如Eden空间、Survivor空间或老年代空间。这种动态划分使得G1能够更灵活地处理不同区域的垃圾回收。
局部收集:G1跳出了传统分代收集的范畴,它可以面向Java堆内存的任意部分进行局部回收,根据Region中垃圾的数量和收集效益来优先处理垃圾回收,实现了"Garbage First"的原则。
大对象处理:G1引入了Humongous区域来存储大对象,大于一个Region容量一半的对象被视为大对象。超大对象则存放在连续的Humongous Region中,这些区域被视为老年代的一部分。
可预测的停顿时间:G1收集器通过维护Region的回收价值和优先级列表,根据用户设定的停顿时间目标(参数-XX:MaxGCPauseMillis)来优先回收收益最大的Region
ZGC收集器
C(Z Garbage Collector)是一款低延迟的垃圾收集器,于JDK 11中引入,由Oracle公司开发。它的目标是实现极低的停顿时间,尽量减少垃圾收集对应用程序的影响,从而满足那些对低延迟和高响应性有要求的Java应用程序