我们的程序运行期间会出现各种各样的问题,稳定性风险是我们每个人都绕不开的话题,由于代码质量不高、架构设计缺陷导致的jvm层面风险,主要是内存溢出、死锁、频繁gc等等,常见的异常有OOM,CPU使用率飙高。这种情况要排查问题的原因,需要我们熟练的使用JVM的工具。
常见的JVM排查工具
jps:虚拟机进程状况工具方式
我们通常使用jps来列出正在运行的java进程,jps可以显示虚拟机执行的主类以及进程的虚拟机ID “LVMID”。jps是我们使用频率最高的工具,其他工具都需要依赖jps查询到的LVMID来进行下一步操作。
jps [option] [hostid]
使用 jps -l 指令,前一列是查询到的LVMID,后一列是主类的全名。
下面的列表是 jps 的一些选项的作用,你可以自己在服务上敲一下命令试试。
jps主要选项 | |
选项 | 作用 |
-q | 只输出LVMID |
-m | 输出虚拟机进程启动时传给main函数的参数 |
-l | 输出主类的全名,如果进程执行的是jar包,输出jar路径 |
-v | 输出虚拟机启动时的JVM参数 |
jstat:虚拟机统计信息监视工具
我们通过jps获取到LVMID,接下来可以使用jstat,jstat可以监控JVM中的类加载信息、内存使用情况、GC情况、JIT信息等。
jstat [option vmid [interval [s|ms] [count] ] ]
其中interval是查询的间隔事件,count是查询的一次。我们看一下jstat -gc 17956 200 3 这个例子,代表每200毫秒执行一次jstat -gc命令,连续执行3次。
查询出来的几个参数含义如下:
- S0、S1:Survivor0、Survivor1 幸存者区
- E:新生代区
- O:老年代区
- P:永久代
- YGC:MinorGC
- YGCT:MinorGC的耗时
- FGC:FullGC
- FGCT:FullGC的耗时
- GCT:GCTime,意思是GC总耗时
下面的列表是jstat的一些选项的作用,你可以自己在服务上敲一下命令试试。
jstat主要选项 | |
选项 | 作用 |
-class | 监视类装载、卸载总量、总空间以及类装载所耗费的时间 |
-gc | 监视JAVA堆情况、包括Eden区、Survivor区、老年代、永久代的容量、GC时间等等 |
-gcutil | 监视内容与-gc基本相同,不过返回的是各个指标的百分比 |
-gcnew | 监视新生代GC情况 |
-gcold | 监视老年代GC情况 |
-printcomplication | 输出已经被JIT编译的方法 |
jinfo:java配置信息工具
查看和调整JVM参数的工具----->jinfo
上面我们讲过,可以使用jps命令的-v选项查看JVM启动时显式指定的参数,其实还有一些没被显式指定的参数,它们使用了默认值,jinfo的-flag选项可以帮我们看到那些默认值、jinfo还有一个厉害的功能,就是它可以在运行期修改参数。
jinfo的命令格式:
jinfo [option] pid
我们再来看一下jinfo -flag的例子,查看CMSInitiatingOccupancyFraction 参数的值:
jinfo -flag CMSInitiatingOccupancyFraction 17956
-XX: CMSInitiatingOccupancyFraction= -1
jmap:Java内存映射工具
你肯定听说过"堆转储快照"以及"dump文件"这两个名词,它们是由jmap创建的。jmap不仅可以获取dump文件,还可以查询永久代、堆空间使用率、GC收集器等信息。
jmap [option] vmid
具体option选项的作用如下:
jmap主要选项 | |
选项 | 作用 |
-dump | 生成Java堆转储快照。格式为-dump:[live,]format=b,file=<filename>,其中live子参数说明是否只有dump出存活的对象 |
-heap | 显示JAVA堆详细信息,如使用哪种垃圾回收器、参数配置、分代状况等 |
-histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
看完上述option选项的作用,接下来我们看一个使用jmap生成一个dump文件的例子:
jhat:虚拟机堆转储快照分析工具
jhat可以分析jmap生成的堆转储快照。jhat生成的dump文件结果报告可以直接在浏览器打开。不过jhat得到分析功能相对来说比较简单,因此我们通常不会直接使用jhat来分析dump文件,可以使用jvisualVM或者arthas等工具。
我们可以看下使用jhat分析dump文件的例子
根据提示在浏览器输入 localhost:7000 就可以查询到dump文件分析结果
jstack:java堆栈跟踪工具
jstack用于生成虚拟机当前时刻的线程快照,也就是"线程dump"文件。线程快照的意思是线程当前的堆栈信息,生成线程快照的主要目的通常是为了定位线程阻塞的原因,如死循环、死锁、IO资源问题等。如果发生线程阻塞,我们可以使用jstack来查看线程堆栈。就可以清晰的看到这些线程在后台执行什么任务、wait什么IO资源。
jstack [option] vmid
具体option选项的作用如下:
jstack主要选项 | |
选项 | 作用 |
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-l | 除堆栈外,显示关于锁的信息 |
总结
遇到线上问题,先用jps查一下进程的LVMID,如果是线程问题直接去看jstack,如果是内存溢出的问题可以配合使用jmap和jhat或者其他分析工具,如果像在问题发生前监控一下内存上涨情况可以使用jstat,并且可以通过jinfo看看内存的大小设置等配置信息。