虚拟机监控工具

jps

显示系统内所有虚拟机进程。

选项 作用
-q 只输出LVMID,省略主类的名称
-m 输出虚拟机进程启动时传递给主类main()函数的参数
-l 输出主类的全名,如果进程执行的是jar包,输出jar路径
-v 输出虚拟机进程启动时jvm参数
1
2
3
4
5
6
7
8
[root ~]$ jps -l
87799 org.apache.catalina.startup.Bootstrap
319117 org.apache.catalina.startup.Bootstrap
182013 com.creditease.mscp.boot.MSCPBoot
241863 org.apache.catalina.startup.Bootstrap
262825 org.apache.catalina.startup.Bootstrap
82480 org.apache.catalina.startup.Bootstrap
261415 sun.tools.jps.Jps

jstat

用于收集虚拟机各方面的运行数据。

选项 作用
-class 监视类的装载、卸载数量以及类的装载总空间和耗费时间等
-gc 监视Java堆,包含eden、2个survivor区、old区和永久带区域的容量、已用空间、GC时间合计等信息
-gccapcity 监视内容与-gc相同,但输出主要关注Java区域用到的最大和最小空间
-gcutil 监视内容与-gc相同,但输出主要关注已使用空间占总空间的百分比
-gccause 与-gcutil输出信息相同,额外输出导致上次GC产生的原因
-gcnew 监控新生代的GC情况
-gcnewcapacity 与-gcnew监控信息相同,输出主要关注使用到的最大和最小空间
-gcold 监控老生代的GC情况
-gcoldcapacity 与-gcold监控信息相同,输出主要关注使用到的最大和最小空间
-gcpermcapacity 输出永久带用到的最大和最小空间
-compiler 输出JIT编译器编译过的方法、耗时信息
-printcompilation 输出已经被JIT编译的方法
1
2
3
[weblogic@vm-10-112-180-180 ~]$ jstat -gc 87799
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
13056.0 13056.0 301.9 0.0 104960.0 15747.8 3014656.0 791584.0 131072.0 83501.8 2786 23.422 0 0.000 23.422
S0C 当前survivor space 0 的总容量 (KB)
S1C 当前survivor space 1 的总容量 (KB)
S0U 当前survivor space 0 已使用的容量 (KB)
S1U 当前survivor space 1 已使用的容量 (KB)
EC 当前 eden space 总容量 (KB)
EU 当前eden space已经使用的容量 (KB)
OC 当前 old space 总容量 (KB)
OU 当前old space 已使用容量(KB)
PC 当前 permanent space 总容量(KB)
PU 当前 permanent space 已使用容量 (KB)
YGC 从应用启动时到现在,年轻代young generation 发生GC Events的总次数
YGCT 从应用启动时到现在, 年轻代Young generation 垃圾回收的总耗时
FGC 从应用启动时到现在, full GC事件总次数
FGCT 从应用启动时到现在, Full sc总耗时
GCT 从应用启动时到现在, 垃圾回收总时间. GCT=YGCT+FGCT

jinfo

显示虚拟机配置信息。实时的查看和调整JVM的各项参数。可以使用-flag [+/-]name或者-flag name=value修改一部分运行期可写的虚拟机参数。

输出gc日志

1
2
3
D:\>jinfo -flag +PrintGCDetails 4192

D:\>jinfo -flag +PrintGC 4192

jmap

生成虚拟机的内存转储快照(heapdump文件)

选项 作用
-dump 生产Java堆转储快照。格式为:-dump[live, ]format=b, file=。其中live子参数说明是否只dump存活的对象。
-finalizerinfo 显示在F-Queue中等待finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效。
-heap 显示Java堆详细信息,如使用哪种回收器、参数配置、分代情况等。只在Linux/Solaris平台下有效。
-histo 显示堆中对象统计信息,包括类、实例数量、合计容量。-histo:live,这个命令执行,JVM会先触发gc,然后再统计信息。
-permstat 以Classloader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效。
-F 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生产dump快照。只在Linux/Solaris平台下有效。
1
2
3
4
5
6
7
8
9
10
[root]$ jmap -dump:format=b,file=dump.hprof 182013
Dumping heap to /app/weblogic/pop-interface/logs/dump.hprof ...
Heap dump.hprof file created
[root]$ ll
total 133652
drwxr-xr-x 2 weblogic weblogic 40960 May 17 07:10 bak
-rw-rw-r-- 1 weblogic weblogic 42591197 May 17 15:56 catalina.2018-05-17.out
-rw------- 1 weblogic weblogic 92541638 May 17 15:57 dump.hprof
-rw-rw-r-- 1 weblogic weblogic 1638325 May 17 15:56 gc.log
-rw-rw-r-- 1 weblogic weblogic 23925 May 17 15:57 localhost_access_log.2018-05-17.log

可以使用jvisualvm来分析生产的dump文件。

img

jstack

显示虚拟机上的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的就定位线程出现长时间停顿的原因,如线程死锁、死循环等。

1
jstack pid

jcmd

在JDK1.7以后,新增了一个命令行工具 jcmd。他是一个多功能的工具,可以用它来导出堆、查看Java进程、导出线程信息、执行GC、还可以进行采样分析。

1
jcmd -l	#查看所有的进程列表信息。类似jps
1
jcmd pid help	#列出当前运行的java进程可以执行的操作,详细操作请看下表
常用命令 详情 举例
VM.unlock_commercial_features 取消锁定商业功能。 jcmd pid VM.unlock_commercial_features
JFR.start 启动jfr。开启去必须线取消锁定商业功能。 jcmd pid JFR.start name=abc,duration=120s
JFR.dump 等待至少duration后,执行命令(注意,文件名必须为.jfr后缀),使用jmc打开生成的jfr文件。 jcmd pid JFR.dump name=abc,duration=120s filename=abc.jfr
JFR.stop 停止jfr。 jcmd pid JFR.stop name=abc,duration=120s
JFR.check 检查JFR状态。 jcmd pid JFR.check name=abc,duration=120s
GC.class_histogram 查看系统中类统计信息。这里和jmap -histo pid的效果是一样的。这个可以查看每个类的实例数量和占用空间大小。 jcmd pid GC.class_histogram
Thread.print 查看线程堆栈信息。该命令jstack命令。 jcmd pid Thread.print
GC.heap_dump 查看 JVM 的Heap Dump。跟 jmap命令:jmap -dump:format=b,file=heapdump.phrof pid 效果一样。导出的 dump 文件,可以使用MAT 或者 Visual VM 等工具进行分析。 jcmd pid GC.heap_dump dump.hprof
VM.system_properties 查看 JVM 的属性信息。 jcmd pid VM.system_properties
VM.flags 查看 JVM 的启动参数。 jcmd pid VM.flags
VM.command_line 查看 JVM 的启动命令行。 jcmd pid VM.command_line
GC.run_finalization 执行一次finalization操作,相当于执行java.lang.System.runFinalization()。 jcmd pid GC.run_finalization
GC.run 对 JVM 执行 java.lang.System.gc()。告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的。 jcmd pid GC.run
PerfCounter.print 查看 JVM 性能相关的参数。 jcmd pid PerfCounter.print
VM.version 查看目标jvm进程的版本信息。 jcmd pid VM.version

实践

查看GC log

1
2
3
4
2018-06-04T16:12:17.393+0800: 336894.721: [GC2018-06-04T16:12:17.393+0800: 336894.721: [ParNew: 1677824K->7137K(1887488K), 0.0167290 secs] 2058871K->388184K(3984640K), 0.0172050 secs] [Times: user=0.10 sys=0.00, real=0.02 secs] 
2018-06-04T16:12:39.083+0800: 336916.411: [Full GC2018-06-04T16:12:39.083+0800: 336916.411: [CMS: 381047K->380283K(2097152K), 1.3115720 secs] 481767K->380283K(3984640K), [CMS Perm : 171267K->171267K(285428K)], 1.3120450 secs] [Times: user=1.31 sys=0.00, real=1.31 secs]

[ParNew(使用ParNew作为年轻代的垃圾回收期): 43296K(年轻代垃圾回收前的大小)->7006K(年轻代垃圾回收以后的大小)(47808K)(年轻代的总大小), 0.0136826 secs(回收时间)] 44992K(堆区垃圾回收前的大小)->8702K(堆区垃圾回收后的大小)(252608K)(堆区总大小), 0.0137904 secs(回收时间)] [Times: user=0.03(Young GC用户耗时) sys=0.00(Young GC系统耗时), real=0.02 secs(Young GC实际耗时)]

高CPU占用

一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环或者是因为内存不足和导致频繁的full gc。

1、查看当前cpu的使用情况

top命令

img

2、查看当前pid下的线程情况

ps -mp pid -o THREAD,tid,time

img

3、将线程id转换为16进制

printf “%x\n” tid

img

4、打印线程快照信息

jstack pid |grep tid -A 30

img

高内存占用

1、查看当前内存的使用情况

命令top

img

2、查看当前内存活跃的对象和占用内存大小

jmap -histo:live pid

img