JDK8中常用如下的垃圾收集器,它们分别运用在年轻代和老年代:
ParNew : 年轻代垃圾收集器,多线程,采用标记—复制算法。
CMS:老年代的收集器,全称(Concurrent Mark and Sweep),是一种以获取最短回收停顿时间为目标的收集器。
可以通过如下JVM参数进行配置:
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
一、ParNew
意为“Parallel New Generation”,需要说明的是, ParNew虽然是个minor gc,但它会Stop-The-World。因此ParNew间隔时间越长越好,并且每次执行的时间越短越好。下面是一次ParNew打印的日志
[GC (Allocation Failure) [ParNew: 367523K->1293K(410432K), 0.0023988 secs] 522739K->156516K(1322496K), 0.0025301 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
其中的时间分别表示如下:
- 用户态消耗的CPU时间
- 内核态消耗的CPU事件
- 操作从开始到结束所经过的墙钟时间(Wall Clock Time)
这里需要说明一下CPU时间与墙钟时间的区别:
墙钟时间包括各种非运算的等待耗时,例如等待磁盘I/O、等待线程阻塞,而CPU时间不包括这些耗时,但当系统有多CPU或者多核的话,多线程操作会叠加这些CPU时间,所以读者看到user或sys时间超过real时间是完全正常的。
因此在查看GC日志时,主要关注real对应的时间。
二、CMS
意为“Concurrent Mark Sweep”,CMS主要分为如下几个阶段
- CMS-initial-mark # 需要Stop the word
- CMS-concurrent-mark
- CMS-concurrent-preclean
- CMS-concurrent-abortable-preclean
- CMS-remark # 需要Stop the word
- CMS-concurrent-sweep
- CMS-initial-mark
这里需要特别关注CMS-initial-mark和CMS-remark这2个阶段,因为这2 个阶段需要Stop-The-World。对于CMS来说,也是间隔时间戟长越好,每次执行时间越短越好。
关于这几个阶段GC日志的具体内容,可以到网上查找,这里就不再一一说明了。
另外,关于CMS需要关注2个JVM参数:
-XX:CMSInitiatingOccupancyFraction
-XX:+UseCMSInitiatingOccupancyOnly
1、-XX:CMSInitiatingOccupancyFraction
老年代堆占用了多大比例时,会做一次CMS。默认值是-1,表示不启用。大于等于0则直接取其值,小于0则根据如下公式来计算:
((100 - MinHeapFreeRatio) + (double)( CMSTriggerRatio * MinHeapFreeRatio) / 100.0) / 100.0
CMSTriggerRatio在JDK1.8是80
MinHeapFreeRatio在JDK1.8是40
2、-XX:+UseCMSInitiatingOccupancyOnly
一直使用上述设定的阈值,如果不指定,JVM仅在第一次使用设定值,后续则自动调整。
三、DefNew
意为“Default New Generation”,新生代Serial收集器中。由于用的少,就不介绍了。它打印的GC日志大概是这样的。
[DefNew: 78656K->78656K(78656K), 0.0000398 secs]
四、一些重要的JVM参数
-Xms -XX:InitialHeapSize 堆内存初始大小
-Xmx -XX:MaxHeapSize 堆内存最大大小
-Xss -XX:ThreadStackSize 单个线程栈大小
-XX:NewSize 新生代初始堆大小
-XX:MaxNewSize 新生代最大堆大小
-XX:OldSize 老年代堆大小
-XX:MetaspaceSize 元数据区初始值(JDK1.8)
-XX:MaxMetaspaceSize 元数据区最大值(JDK1.8)
-XX:SurvivorRatio 用来设置新生代中eden空间和from/to空间的比例.
-XX:MaxTenuringThreshold 对象从新生代晋升到老年代的年龄阈值,默认值15
-XX:NewRatio 老年代/新生代的堆内存比例,在设置了-XX:MaxNewSize的情况下,-XX:NewRatio的值会被忽略-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintGC
-XX:+PrintGCDetails
使用jinfo查看进程的JVM参数
jinfo -flags <pid>
查看JVM参数默认值的方法
java -XX:+PrintFlagsFinal -version
参考文档
GC(Allocation Failure)引发的一些JVM知识点梳理
https://blog.csdn.net/zc19921215/article/details/83029952
[case9]频繁GC (Allocation Failure)及young gc时间过长分析
https://segmentfault.com/a/1190000013509330
JVM常用参数说明
https://www.cnblogs.com/shjr/p/14667216.html
CMS的CMSInitiatingOccupancyFraction解析
https://blog.csdn.net/insomsia/article/details/91802923
CMS收集器几个参数详解 -XX:CMSInitiatingOccupancyFraction, CMSFullGCsBeforeCompaction
https://blog.csdn.net/liubenlong007/article/details/88541589
Java开发中的问题排查,性能调优,先学会阅读GC日志
https://cloud.tencent.com/developer/article/1478419
JVM中的垃圾收集器 -- CMS
https://blog.csdn.net/wodewutai17quiet/article/details/48895893