2020-heibaiying-JVM 性能监控之命令行工具
JVM 性能监控之命令行工具
一、简介
在bin
文件夹下,除了提供有 javac
、java
这两个常用的编译和运行工具外,还提供了一系列命令行工具用于
二、jps
jps(JVM Process Status Tool)用于列出正在运行的虚拟机进程的主类名称和
C:/Users>jps
10848 Main
14560 Jps
7040 Launcher
11572
9492 DeadLockTest
7868 JConsole
可选参数有 -v
,用于输出虚拟机进程启动时的
三、jstat
jstat(JVM Statistics Monitoring Tool)用于监视虚拟机的运行状态。使用格式如下:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
其中 option
的所有可选值如下:
选项 | 作用 |
---|---|
-class | 监视类加载、卸载数量、总空间以及类装载所耗费的时间 |
-gc | 监视 |
-gccapacity | 与 |
-gcutil | 与 |
-gccause | 与 |
-gcnew | 监视新生代垃圾回收的状况 |
-gcnewcapacity | 与 |
-gcold | 监视老年代垃圾回收的状况 |
-gcoldcapacity | 与 |
-compiler | 输出即时编译器编译过的方法、耗时等信息 |
-printcompilation | 输出已经被即时编译的方法 |
命令行中的 interval
表示监控的时间间隔,count
表示监控次数。示例如下:
jstat -gc 9492 3s 5 # 每3s输出一次,一共输出5次

输出信息中各个参数含义分别如下:
- S0C:
survivor 0 的容量大小,单位kB ; - S1C:
survivor 1 的容量大小,单位kB ; - S0U:
survivor 0 已使用的空间大小,单位kB ; - S1U:
survivor 1 已使用的空间大小,单位kB ; - EC:
Eden 区的容量大小,单位kB ; - EU:
Eden 区已使用的空间大小,单位kB ; - OC:老年代的容量大小,单位
kB ; - OU:老年代已使用的空间大小,单位
kB ; - MC:
Metaspace 容量大小,单位kB ; - MU:
Metaspace 已使用的空间大小,单位kB ; - CCSC:压缩类的空间大小,单位
kB ; - CCSU:压缩类已使用的空间大小,单位
kB ; - YGC:年轻代垃圾回收的次数;
- YGCT: 年轻代垃圾回收所消耗的时间;
- FGC:老年代垃圾回收的次数;
- FGCT:老年代垃圾回收所消耗的时间;
- GCT:垃圾回收所消耗的总时间。
以上是-gc
时的输出结果,不同
四、jinfo
jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机的各项参数。使用格式如下:
jinfo [option] <pid>
其中 option
支持以下可选项:
- -flag name :输出指定的虚拟机参数的值;
- -flag [+|-]name :启用或禁用指定名称的虚拟机参数;
- -flag name=value :设置虚拟机参数的值;
- -flags :以键值对的方式输出
JVM 的相关属性; - -sysprops:以键值对的方式输出
Java 相关的系统属性。
示例如下:
jinfo -flags 13604
jinfo -flag CMSInitiatingOccupancyFraction 13604

五、jmap
jmap(Memory Map for Java)命令主要用于生成堆转储快照(一般称为
jmap [option] <pid>
其中 option
支持以下可选项:
选项 | 作用 |
---|---|
-dump:[live,]format=b,file= | 生成 |
-finalizerinfo | 显示在 |
-heap | 显示 |
-histo[:live] | 显示堆中对象的统计信息,包括类、实例数量、合计容量 |
-permstat | 以 |
-F | 当虚拟机进程堆 只在 |
示例如下:
jmap -dump:format=b,file=test.bin 3260

六、jhat
jhat(JVM Heap Analysis Tool)命令主要用来分析
public class StackOverFlowTest {
private static List<StackOverFlowTest> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
while (true) {
list.add(new StackOverFlowTest());
Thread.sleep(10); //因为只是演示,所以休眠一下,避免生成的堆转储文件过大,导致分析时间过长
}
}
}
其最终会抛出 java.lang.OutOfMemoryError: Java heap space
异常,意味着在


session
选项卡,并使用 Open Snapshot
打开

之后程序会自动进行分析,分析结果如下:

通过以上可视化的统计结果,我们就可以很快定位到导致内存溢出的原因。
七、jstack
jstack(Stack Trace for Java)命令用于生成虚拟机的线程快照(一般称为
jstack -F [-m] [-l] <pid>
各选项的作用如下:
选项 | 作用 |
---|---|
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-m | 除堆栈外,显示关于锁的附加信息 |
-l | 如果有调用本地方法的话,则可以显示 |
假设我们的程序中存在如下死锁:
public class DeadLockTest {
private static final String a = "a";
private static final String b = "b";
public static void main(String[] args) {
new DeadLockTest().deadlock();
}
private void deadlock() {
new Thread(() -> {
synchronized (a) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
}
}
}).start();
new Thread(() -> {
synchronized (b) {
synchronized (a) {
}
}
}).start();
}
}
此时使用
jstack 8112
输出结果如下:

从输出中结果中可以看出,出现了一个死锁,该死锁由线程<0x00000000d6d8d610>
,并尝试获取 <0x00000000d6d8d640>
对象的锁;但是<0x00000000d6d8d640>
,并尝试获取 <0x00000000d6d8d610>
对象的锁,由此导致死锁。
参考资料
- 主要参考自:周志明
. 深入理解Java 虚拟机(第3 版). 机械工业出版社, 2019-12 ,想要深入了解虚拟机的话,推荐阅读原书。 - 官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/s11-troubleshooting_tools.html#sthref327