JVM系列(5)-HotSpot 2 垃圾收集器

今天继续HotSpot的学习,聊聊垃圾收集器。

之前讲过垃圾收集算法,可以参考这里JVM系列(4)-垃圾收集算法,垃圾收集算法讲的是思想或者理论,垃圾收集器呢,就是其实现。


知识点1:HotSpot有哪些垃圾收集器呢?



参阅《深入理解Java虚拟机 JVM高级特性与最佳实践》,以JDK 1.7 Upgrade 14之后的HotSpot虚拟机为例。下图是HotSpot包含的垃圾收集器。


按官方的解释,Serial、ParNew/Parallel Scavenge属于新生代收集器;CMS、Serial Old(MSC)、Parallel Old是老年代收集器,G1即在老年代也在新生代。


为什么会有这么多收集器,有没有一个放之四海皆试用的垃圾收集器?

答案:没有,不同的垃圾收集器适用于不同的应用场景,没有万能的收集器。可以根据需求搭配不同的垃圾收集器,如上图,之间有连线的就是可以搭配使用的,没有连线的就是不能搭配使用。


下面逐一讲解各个垃圾收集器。


知识点2:Serial收集器


Serial收集器负责新生代的垃圾回收,采用的是复制回收算法

这是一个单线程的收集器,也就是只使用一个收集线程来收集垃圾,而且更重要的是收集的时候,需要“Stop the world”,也就是暂停所有的执行线程,直到垃圾收集结束。



知识点2:ParNew收集器


这个没啥讲的,就是Serial收集器的多线程版本,还有一点,ParNew多用于Server模式,除了Serial收集器,它是唯一可以和CMS搭配使用的,CMS是重点,后面会讲到。

默认开启的线程数与CPU的个数相同。

单CPU情况下,比不过Serial收集器。


知识点3:Parallel Scavenge收集器


Parallel Scavenge和ParNew有很多相似之处。首先他们都负责收集新生代垃圾,其次,它们采用的收集算法都是“复制”,最后它们都是并行的多线程收集器。

Parallel Scavenge的关注点是吞吐量。


吞吐量 = 运行用户代码时间 / 运行用户代码时间 + 垃圾收集时间


参数-XX:UserAdaptiveSizePolicy可以开启自适应策略。


知识点4:Serial Old收集器


Serial Old是Serial收集器的老年代版本,它也是一个单线程收集器,但使用的是“标记-整理”回收算法。

这个收集器主要应用与Client模式的虚拟机,如果用在Server模式,主要有两个目的:一个是与Parallel Scavenge搭配使用,另一个是给CMS收集器做后备。


知识点5:Parallel Old收集器


Parallel Old是Parallel Scavenge的老年代版本,正如Serial Old是Serial收集器的老年代版本一样。在Parallel Old出现之前,Parallel Scavenge只能和Serial Old收集器搭配使用,由于Serial Old是单线程的,并且需要“Stop the world”,在性能上拖累了Parallel Scavenge收集器。Parallel Old出现之后,情况就不同了,在注重吞吐量和CPU资源敏感的场合,很适用Parallel Scavenge和Parallel Old的组合。


Parallel Old收集器采用的是标记-整理算法。


知识点6:CMS收集器


CMS收集器关注的点是“最短停顿时间”,我们知道,像Serial收集器,在垃圾收集的时候,需要停顿所有执行线程,那这个停顿的时间能不能尽可能的短呢?

CMS就是追求这个“最短停顿时间”的收集器。插播一句,像Parallel Scavenge收集器关注的则是“吞吐量”,高吞吐量则意味着高效利用了CPU。在注重交互的场景,客户更在意的是停顿时间,所以我们可以选择CMS收集器;在没有太多交互而存在大量计算的场景下,很适合选用Parallel Scavenge这类关注“吞吐量”的收集器。


CMS = Current Mark Sweep,从名字可以看出,CMS采用的是标记-清除算法。


运作过程如下图,主要有4个阶段:初始标记、并发标记、重新标记、并发清除。其中初始标记和重新标记,需要“Stop the world”,因为要标记哪些是垃圾,所以得停顿下啊,不能一边打扫,一边扔垃圾不是。而消耗时间较长的并发标记和并发清除则不需要停顿用户线程。


缺点:在并发标记和并发清除阶段,因为是和用户线程并发执行的,要消耗一部分资源,如果用户线程本身资源就很紧张,可能会导致应用程序执行变慢。


还有就是CMS收集器无法处理“浮动垃圾”。什么是“浮动垃圾”?我们知道在并发清除阶段,用户线程还是在执行的,也就是在并发清除的过程中,用户线程还是会产生垃圾的,这部分垃圾因为没有被标记,也就清除不了,这就是“浮动垃圾”。


最后是内存碎片,我们知道CMS采用的是标记-清除算法,这种算法本身就会产生内存碎片。可以通过一些参数,设置在什么情况下执行一下碎片整理。


知识点7:G1收集器


这个收集器很牛逼,像上面讲的收集器,都需要两两搭配使用,比如Serial收集器和Serial Old收集器,一个负责年轻代,一个负责老年代。而G1收集器单此一个挑大梁,同时负责新生代和老年代。不像前面讲的收集器,它们把堆空间会分为两个不同的连续区间(新生代区和老年区)。G1收集器则是把堆空间划分为多个不同的region,新生代region和老年代region也不是连续的。像下面这样。


G1会在后台维护一个列表,在允许的收集时间内,优先回收价值最大的region,也就是释放空间最多的region。


知识点7:GC日志关键字


采用的收集器不同,日志中记录的新生代名称也不同。

Serial : DefNew = Default New Generation

ParNew : ParNew = Parallel New Generation

Parallel Scavenge : PSYoungGen = Parallel Scavenge Young Generation


Tenured : 老年代

Perm : 持久代


知识点8:垃圾收集器参数总结


有个博客写的挺详细的,我就不做重复劳动了。

下面内容转自博客:http://blog.csdn.net/huxian1234/article/details/17163023

垃圾收集器参数总结

-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  并行回收GCParallel 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

今天就到这儿,明天继续^_^。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值