上篇文章说jvm的实际运行情况。
一、Arthas介绍
因为arthas完全是java代码写的,我们直接用命令启动:
Java -jar arthas-boot.jar
启动成功后,选择我们项目的进程。
进入我们可用dashboard查询看板。
之后可以看到76线程较高,用thread 线程id来查看哪些异常导致cpu过高。
arthas的 jad命令可以反编译线上代码。
当我们系统上线,但我们感觉并没有把代码上线,或者上错分支,这时候怎么办呢,于是可以用这个命令来反编译代码,看看是否正常。
当我们需要查看某个类里对象的值,这时候可以通过
ognl @com.zto.jvm.JvmController@hashSet
甚至调用线上代码修改里面的值:
ognl @com.zto.jvm.JvmController@hashSet.add(“arthasAdd”)
二、GC日志详解
Java -jar -Xloggc:./gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps -XX:+PrintGCCause
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100M service-eureka-server.jar
这里解释下会把时间戳替换成%t
陆续分段打到10个文件,打100M,保留10个文件,超过一个G则会覆盖。
Parallel:
图上是parallel策略垃圾收集,可以看到minor GC和fullGC。
年轻代在minorGC之前有57M,发生垃圾收集之后成为65M,年轻代总大小为66M。
218M为堆的总大小。
fullGC原因在日志文件也可以看到,原因是Metadata GC threshold,元空间不够。
为什么都是元空间不够导致的fullGC呢,因为项目刚启动,加载类,每次元空间加载类信息满了,会扩展内存加载新的类,所以项目启动时候会因为元空间不够多次fullGC。
CMS:
这时候我们需要改jvm启动参数:
-Xloggc:d:/gc-cms-%t.log
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-Xms50M -Xmx50M
首先垃圾收集器改为parNew和CMS,为了快速内存溢出,我们把堆大小设置成50M。
从这些日志可以看到,我们cms垃圾收集器的过程,初始化标记,是会STW的,然后会并发标记,之后重新标记又会STW,之后并发清理会有新对象,这时候标记成黑色方便下次清理,这属于浮动垃圾。
当进入的对象速率超过垃圾回收器回收对象时间,这时候则会单线程serail垃圾回收器回收,从图中Allocation Failture就可以看到内存溢出会进入单线程回收。
G1:
这时候我们需要改jvm启动参数:
-Xloggc:d:/gc-g1-%t.log -XX:+UseG1GC
这是G1的初始标记,并发标记,最终标记,回收。
Java -XX:+PrintFlagsInitial打印默认值。
Java -XX:+PrintFlagsFinal打印运行程序生效值。