JavaJVM

JVM GC调优入门

2018-05-07  本文已影响350人  樂浩beyond

JVM GC调优入门

这篇文章会介绍几个常用的调优参数,再通过两个案例介绍如何进行JVM GC调优。阅读这篇文章的前提是假设大家已经对JVM内存模型、JVM的垃圾回收算法、JVM的垃圾回收器都比较熟悉了。

JVM调优是必须的吗?

阅读下面的内容之前首先抛出这个问题:GC调优对于java服务是必须的吗?实际上,我感觉80%的java的程序员在实际工作中都没有碰到过GC调优吧,这是因为多数的Java应用不需要在服务器上进行GC优化,多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题,需要记住一点:GC调优是最后要做的工作

GC调优的目的可以总结为下面两点:

减少对象晋升到老年代的数量

分代垃圾回收是Oracle JVM中回收思想。 我们知道在Eden区创建的对象,在from Survivor 复制到to Survivor区之后,达到一定年龄就进入了老年代。有些对象因为比较大就直接进入了老年代。在老年代的GC时间相比于年轻代时间更长。因此,减少对象进入老年代可以降低Full GC的频率

减少FullGC的执行时间

Full GC的时间比Minor GC要长。所以如果执行太长时间的Full GC(超过1秒),就会发生超时错误

影响GC的参数

JVM调优主要用到参数罗列在下面的两张表中。主要分为内存参数和垃圾类型参数。GC优化的过程就是在调试这些参数的过程。

下表是与JVM内存相关的参数:


image.png

比较常用的参数是 -Xms, -Xmx-XX:NewRatio

下表展示的垃圾收集器类型的可选参数:


image.png

不同的垃圾回收器与老年代年轻代的关系如下:


image.png

还有一个常用的参数是-XX:+PrintGCDetails
通过 -XX:+PrintGCDetails可以查看具体的GC日志。下面的两张图分别介绍Full GC与Minor GC日志里的各个字段。

image.png image.png

监控命令

设置好上面将的参数后,可以通过监控查看我们优化的。监控可以分为命令监控图形化监控。关于图形化监控可用工具比较常见的有JConsole和VisualVM,可以参考这篇文章。这里不做过多介绍。这节主要介绍个常用的监控命令,在下面的案例中也是有用到的。

jps 命令格式:jps [option] [hostid]
jps命令用于查询正在运行的JVM进程,常用的参数为:
-q:只输出LVMID,省略主类的名称
-m:输出虚拟机进程启动时传给主类main()函数的参数
-l:输出主类的全类名,如果进程执行的是Jar包,输出Jar路径
-v:输出虚拟机进程启动时JVM参数

例子:


image.png

jstack 命令格式:jstack [option] vmid
用于生成当前JVM的所有线程快照,线程快照是虚拟机每一条线程正在执行的方法,目的是定位线程出现长时间停顿的原因。
-F:当正常输出的请求不被响应时,强制输出线程堆栈
-l:除堆栈外,显示关于锁的附加信息
-m:如果调用到本地方法的话,可以显示C/C++的堆栈

例子


image.png

jmap 命令格式:jmap [option] vmid
用于显示当前Java堆和永久代的详细信息(如当前使用的收集器,当前的空间使用率等)
-dump:生成java堆转储快照
-heap:显示java堆详细信息(只在Linux/Solaris下有效)
-F:当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照(只在Linux/Solaris下有效)
-histo:显示堆中对象统计信息

例子


image.png

jstat命令格式:jstat [option vmid [interval[s|ms] [count]]]
jstat可以实时显示本地或远程JVM进程中类装载、内存、垃圾收集、JIT编译等数据
-class:监视类装载、卸载数量、总空间及类装载所耗费的时间
-gc:监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息
-gccapacity:监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间
-gcutil:监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause:与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew:监视新生代GC状况
-gcnewcapacity:监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间
-gcold:监视老年代GC情况
-gcoldcapacity:监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间
-gcpermcapacity:输出永久代使用到最大和最小空间
-compiler:输出JIT编译器编译过的方法、耗时等信息

例子


image.png

命令jstat -gc 309 1000 5代表着:搜集vid为309的java进程的整体gc状态, 每1000ms收集一次,共收集5次

案例

下面两个案例是网友的JVM调优过程,作者过程思路清晰,步步分析到位,在这里分享给大家:
1、CMS调优
2、OOM问题调优

总结

JVM调优在实际工作中用到的比较少,但是这也是作为java程序员必须掌握的基本技能。真正熟练的使用GC调优,是建立在多次进行GC监控和调优的实战经验上的

下面罗列了几个数据作为参考,如果GC执行时间满足下列所有条件,就没有必要进行GC优化了:

Minor GC执行非常迅速(50ms以内)

Minor GC没有频繁执行(大约10s执行一次)

Full GC执行非常迅速(1s以内)

Full GC没有频繁执行(大约10min执行一次)


PS:如果你要应付面试上的JVM题目。这可以参考这篇文章jvm知识点总览

参考文章:How to Tune Java Garbage Collection

上一篇下一篇

猜你喜欢

热点阅读