- 首先查看Full GC花费的时间,比如2秒或以上,这种一般都需要尽快进行调优了
[root@localhost ~]# jstat -gcutil 5524 2000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
99.96 0.00 83.06 25.56 97.56 96.66 4 0.188 1 0.027 0.215
99.96 0.00 83.06 25.56 97.56 96.66 4 0.188 1 0.027 0.215
99.96 0.00 83.06 25.56 97.56 96.66 4 0.188 1 0.027 0.215
99.96 0.00 83.06 25.56 97.56 96.66 4 0.188 1 0.027 0.215
S0:幸存区1占用率
S1:幸存区2占用率
E:Eden区占用率
O:老年区占用率
M:元数据区(java8,相当于java7及之前的永久代的概念)使用大小
ccs:压缩后使用率
YGC:young gc 次数,
YGCT:young gc耗时
FGC:full gc次数
FGCT:full gc耗时
GCt:GC共耗时
可以通过每次GC后 各区的占用率发生的变化来判断GC成果,
如果FULL GC频繁说明内存已经存在溢出可能或已经溢出,应用处理能力将会下降甚至停摆,因为大量时间在GC上面
如果YGC频繁,s0,s1,eden区使用率又没有明显下降,也需要注意,他们中的数据在增长到一定程度时,可能会进入old区,需要观察full gc情况
如果每次YGC后,但是s0,s1,eden区内存使用下降明显,一般不会有问题,说明jvm中存在了占比较重的短生命周期对象,能及时回收掉释放给其它请求或任务使用,只要保持获取与释放平衡就不会有太大问题
- 堆dump来分析验证内存溢出的原因
堆dump是把内存情况按一定格式输出到文件,可用于检查Java 内存中的对象和数据情况。可使用JDK中内置的jmap命令创建堆dump文件。创建文件过程中,Java进程会中断,因此不要在正常运行时系统上做此操作。
- 例如用内存分析工具JVisualVM分析内存分配情况
- 一般我们的应用启动脚本里面会打印GC的日志,并且会提前设定阈值,在80%的可能就就会触发Gc了
- 正常情况下,我们会优先看下云服务器的CPU、内存、磁盘等的状况,用下top命令
- 借助arthas强大的工具分析
dashboard观察一下HTTP请求的qps, rt, 错误数, 线程池信息等等
thread -n 3查看当前最忙的前N个线程并打印堆栈
thread -b 查看线程死锁
jvm查看当前jvm信息
用trace命令分析方法内部调用路径,并输出方法路径上的每个节点上耗时
- 通常CMS GC比Parallel GC要好,因为CMS GC的执行中并不会伴随内存压缩,因此GC速度会更快一些
- 如果调整好参数后,需要做性能测试,然后连续观察几天
关于jvm调优的一些小tips:
- 把Xms和Xmx设置为相同,这样可以减少GC后重新分配带来的性能开销
- 把MaxPermSize和MinPermSize设置成一样(JDK8开始,没有了Perm,代替为元空间。元空间是直接存在内存中,不在JVM里面)
Comments | NOTHING