垃圾收集器

本文介绍了HotSpot JVM的垃圾收集器,包括新生代和老年代收集器。如Serial、ParNew等新生代收集器,Serial Old、Parallel Old等老年代收集器,还介绍了CMS、G1收集器。阐述了各收集器的算法、优缺点及适用场景,如CMS注重低停顿,Parallel Scavenge关注吞吐量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HotSpot JVM收集器

上图有七个垃圾收集器,分为两块,上块儿是新生代收集器,下块儿是老年代收集器。如果俩个收集器之间有连线,就说明他们可以搭配使用


Serial收集器

新生代中的单线程收集器,使用复制算法,是JVM client端的默认收集器。

优点:简单而高效(与其他收集器的单线程相比) 缺点:由于是单线程,进行垃圾收集的时候必须暂停其他线程




ParNew收集器

是Serial收集器的多线程版本,除了使用多线程进行垃圾回收外,其它策略与Serial收集器基本相同

Server模式下虚拟机首选的新生代收集器,除了Serial收集器外,只有它能与CMS收集器相配合



Parallel Scavenge收集器

新生代收集器,使用复制算法,并行的多线程收集器

Parallel Scavenge收集器关注点不是缩短用户线程的停顿时间,关注于达到一个可控制得吞吐量(Throughput);吞吐量:吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

停顿时间越短关于于与用户交互,高吞吐量则为了高效的利用cpu时间,主要适合后台运算而不需要太多的交互任务


Serial Old收集器

Serial收集器的老年代版本,是单线程收集器,使用“标记-整理”算法,在client端的JVM中使用

用途:作为CMS收集器的后备选案



Parallel Old收集器

Parallel Scavenge收集器的老年代版本,使用多线程和“整理-标记”算法

在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器



CMS收集器(Concurrent Mark Sweep)

目的:获取最短回收停顿时间,重视服务的响应速度,基于“标记-清除”算法

过程有4个步骤:

1.初始标记(CMS initial mark)

2.并发标记(CMS concurrent mark)

3.重新标记(CMS remark)

4.并发清除(CMS concurrent sweep)

其中,初始标记,重新标记这两个步骤需要“STOP - THE - WORLD”。初始标记仅仅是标记GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Tracing的过程,而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。

总体来说,是与用户线程并发执行的。

主要优点:并发收集,低停顿

缺点:

CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。
CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“,失败后而导致另一次Full  GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,
即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易导致“Concurrent Mode Failure”失败,性能反而降低。
最后一个缺点,CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full  GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full  GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full  GC之后,跟着来一次碎片整理过程。


G1收集器


垃圾收集器参数总结
-XX:+<option> 启用选项
-XX:-<option> 不启用选项
-XX:<option>=<number> 
-XX:<option>=<string>

参数描述

-XX:+UseSerialGC

Jvm运行在Client模式下的默认值,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收
-XX:+UseParNewGC打开此开关后,使用ParNew + Serial Old的收集器进行垃圾回收
-XX:+UseConcMarkSweepGC使用ParNew + CMS +  Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现“Concurrent Mode Failure”失败后的后备收集器使用。
-XX:+UseParallelGCJvm运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge +  Serial Old的收集器组合进行回收
-XX:+UseParallelOldGC使用Parallel Scavenge +  Parallel Old的收集器组合进行回收
-XX:SurvivorRatio新生代中Eden区域与Survivor区域的容量比值,默认为8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold直接晋升到老年代对象的大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
-XX:MaxTenuringThreshold晋升到老年代的对象年龄,每次Minor GC之后,年龄就加1,当超过这个参数的值时进入老年代
-XX:UseAdaptiveSizePolicy动态调整java堆中各个区域的大小以及进入老年代的年龄
-XX:+HandlePromotionFailure是否允许新生代收集担保,进行一次minor gc后, 另一块Survivor空间不足时,将直接会在老年代中保留
-XX:ParallelGCThreads设置并行GC进行内存回收的线程数
-XX:GCTimeRatioGC时间占总时间的比列,默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge 收集器时有效
-XX:MaxGCPauseMillis设置GC的最大停顿时间,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction设置CMS收集器在老年代空间被使用多少后出发垃圾收集,默认值为68%,仅在CMS收集器时有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection
由于CMS收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMS收集器时有效
-XX:+CMSFullGCBeforeCompaction
设置CMS收集器在进行若干次垃圾收集后再进行一次内存碎片整理过程,通常与UseCMSCompactAtFullCollection参数一起使用
-XX:+UseFastAccessorMethods
原始类型优化
-XX:+DisableExplicitGC
是否关闭手动System.gc
-XX:+CMSParallelRemarkEnabled
降低标记停顿
-XX:LargePageSizeInBytes
内存页的大小不可设置过大,会影响Perm的大小,-XX:LargePageSizeInBytes=128m

Client、Server模式默认GC

 新生代GC方式老年代和持久GC方式

Client

Serial 串行GCSerial Old 串行GC
ServerParallel Scavenge  并行回收GCParallel Old 并行GC

Sun/oracle JDK GC组合方式

 新生代GC方式老年代和持久GC方式

-XX:+UseSerialGC

Serial 串行GCSerial Old 串行GC
-XX:+UseParallelGCParallel Scavenge  并行回收GCSerial Old  并行GC
-XX:+UseConcMarkSweepGCParNew 并行GCCMS 并发GC 
当出现“Concurrent Mode Failure”时
采用Serial Old 串行GC
-XX:+UseParNewGCParNew 并行GCSerial Old 串行GC
-XX:+UseParallelOldGCParallel Scavenge  并行回收GCParallel Old 并行GC
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
Serial 串行GCCMS 并发GC 
当出现“Concurrent Mode Failure”时
采用Serial Old 串行GC




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值