下面我将从 命令行工具、可视化工具 和 Java 内置 API 三个层面,为你详细介绍常用的 JVM 监控命令和方法,并提供实际案例。

命令行工具
这些是 JVM 自带的、最常用、最直接的监控工具,通常在 JDK 的 bin 目录下。
jps - Java Virtual Machine Process Status Tool
作用:列出当前正在运行的 Java 进程的 ID 和主类名。
常用选项:
jps:只显示进程 ID 和主类名。jps -l:显示完整的主类包名或 JAR 文件名。jps -v:显示传递给 JVM 的参数。jps -m:显示传递给main方法的参数。
示例:

# 列出所有 Java 进程 $ jps -l 12345 /path/to/your/application.jar 67890 org.apache.catalina.startup.Bootstrap # 查看某个 JVM 的启动参数 $ jps -v 12345 ... -XX:+UseG1GC -Xms512m -Xmx512m ...
jstat - JVM Statistics Monitoring Tool
作用:监控 JVM 的运行时行为,包括堆内存、垃圾回收(GC)情况等,这是分析 GC 问题的核心工具。
常用选项:
jstat -gc <pid>:查看 GC 的详细信息(堆内、堆外)。S0C, S1C:Survivor 0/1 区的容量。S0U, S1U:Survivor 0/1 区的使用量。EC, EU:Eden 区的容量和使用量。OC, OU:Old 区的容量和使用量。MC, MU:元空间的容量和使用量。CCSC, CCSU:压缩类空间容量和使用量。YGC, YGT:Young GC 次数和耗时。FGC, FGCT:Full GC 次数和耗时。GCT:总 GC 耗时。GCC:GC 时间占总时间的百分比。
jstat -gcutil <pid>:以百分比形式展示内存使用情况,更直观。jstat -gccapacity <pid>:查看各内存区域的最大、最小和当前容量。jstat -gcnew <pid>:查看新生代 GC 情况。jstat -gcold <pid>:查看老年代 GC 情况。jstat -t <pid>:在输出中带有一个时间戳,方便观察随时间变化。
示例:
# 每 1 秒监控一次 PID 为 12345 的进程的 GC 情况 $ jstat -gcutil 12345 1000 S0 S1 E O M CCS YGC YGT FGC FGCT GCT GCC LGCT SCT TT FTMT TMA 0.00 0.00 30.45 65.12 95.43 90.12 5 0.123 2 0.456 0.579 0.456 0.01 0.00 2.0 1.0 0.00 0.00 45.12 65.12 95.43 90.12 5 0.123 2 0.456 0.579 0.456 0.01 0.00 2.0 1.0 # 从输出可以看出,Eden 区使用率在持续上升,很快就要触发 Young GC 了。
jmap - Memory Map for Java
作用:生成 Java 堆的转储快照(Heap Dump),或者查看堆内存的详细信息。

常用选项:
jmap -histo <pid>:查看堆中对象的实例数量和大小分布,按占用内存大小降序排列,可以快速发现占用内存最多的对象。num:对象数量。#instances:同上。#bytes:占用总字节数。class name:类名。
jmap -dump:format=b,file=<filename.hprof> <pid>:生成一个二进制的堆转储文件(.hprof),这个文件可以用 MAT 或 VisualVM 等工具分析,是定位内存泄漏的利器。jmap -heap <pid>:查看 JVM 的堆内存配置信息,包括使用的垃圾回收器、各区域大小等。
示例:
# 查看堆中对象的分布 $ jmap -histo 12345 num #instances #bytes class name ---------------------------------------------- 1: 12345 12345000 [C (char数组) 2: 10000 10000000 java.lang.String 3: 50 500000 com.example.YourLeakyObject # 生成堆转储文件 $ jmap -dump:format=b,file=heapdump_12345.hprof 12345
jstack - Java Stack Trace
作用:生成指定 Java 进程的线程快照(Thread Dump),可以用来分析线程状态、死锁、CPU 100% 等问题。
常用选项:
jstack <pid>:生成线程快照。jstack -l <pid>:生成更详细的线程快照,包含锁的信息。jstack -F <pid>:当进程没有响应时,强制生成线程快照。
如何分析线程快照:
- 找到
RUNNABLE状态的线程,特别是 CPU 占用高的线程(nid对应系统的线程 ID,可以用top -H -p <pid>找到具体是哪个线程)。 - 查找
BLOCKED状态的线程,看是否存在线程等待锁。 - 搜索
Found one Java-level deadlock!,直接定位死锁问题。
示例:
# 生成线程快照
$ jstack 12345 > threaddump_12345.log
# 在 Linux 上找到 CPU 占用高的线程
$ top -H -p 12345
# 假设发现 nid 为 0x1234 的线程 CPU 占用 99%
# 然后在 threaddump 文件中搜索 nid 0x1234
$ grep 0x1234 threaddump_12345.log
"Thread-0" #1234 prio=5 os_prio=0 cpu=98.45% elapsed=10.23s tid=0x00007f8c00000400 nid=0x1234 runnable [0x00007f8c...]
java.lang.Thread.State: RUNNABLE
at com.example.YourCPUHungryMethod(Native Method)
at com.example.YourCPUHungryMethod(YourCPUHungryMethod.java:50)
...
jcmd - The Command Line Interface for the JVM
作用:一个多功能工具,可以替代 jps, jinfo, jmap, jstack 等多个命令,它可以直接向 JVM 发送诊断命令,功能更强大。
常用选项:
jcmd:列出所有 Java 进程及其可用的命令。jcmd <pid> help:查看指定进程支持的所有命令。jcmd <pid> GC.heap_info:查看堆内存信息(类似jmap -heap)。jcmd <pid> Thread.print:生成线程快照(类似jstack)。jcmd <pid> GC.class_histogram:查看对象实例分布(类似jmap -histo)。jcmd <pid> GC.heap_dump <filename.hprof>:生成堆转储(类似jmap -dump)。jcmd <pid> VM.native_memory summary:查看本地内存使用情况,对排查 Direct Memory 或 JNI 问题非常有用。
示例:
# 列出所有进程和可用命令 $ jcmd 12345 com.example.Main 67890 org.apache.catalina.startup.Bootstrap # 查看进程 12345 的所有可用命令 $ jcmd 12345 help # 生成堆转储 $ jcmd 12345 GC.heap_dump heapdump_jcmd.hprof # 查看本地内存使用 $ jcmd 12345 VM.native_memory summary
可视化工具
对于不习惯命令行的开发者,可视化工具提供了更直观的界面。
VisualVM
VisualVM 是 JDK 自带的图形化工具,功能非常全面,是监控本地和远程 JVM 的瑞士军刀。
如何启动:
# 在 JDK bin 目录下 $ jvisualvm
主要功能:
- 监控:实时查看 CPU、堆内存、元空间、线程、类加载等信息。
- Sampler:可以对 CPU 和内存进行抽样分析,找出热点代码和内存分配热点。
- Visual GC:实时展示 GC 的活动情况,非常直观。
- OQL (Object Query Language):类似 SQL 的查询语言,可以在堆转储文件中查询对象。
- MBeans:查看和管理 JMX MBeans。
JConsole
JConsole 是另一个 JDK 自带的轻量级监控工具,基于 JMX,功能比 VisualVM 简单,但足以进行基本的监控。
如何启动:
$ jconsole
主要功能:
- 显示内存使用情况。
- 显示线程状态和死锁检测。
- 显示类的加载情况。
- 查看 VM 概要信息。
Eclipse MAT (Memory Analyzer Tool)
专门用于分析堆转储文件(.hprof)的强大工具。
主要功能:
- Leak Suspects Report:自动生成内存泄漏嫌疑报告,直接告诉你哪个对象是泄漏的根源。
- Dominator Tree:支配者树,可以快速找到一组对象中最大的对象,以及被哪些对象强引用。
- Histogram:直方图,查看对象实例数量和大小。
- Path to GC Roots:查看一个对象到 GC Roots 的引用链,这是确定对象为何无法被回收的关键。
Java 内置 API (编程式监控)
在代码中集成监控,可以实现更灵活、自动化的监控。
java.lang.management 包
提供对 JVM 和操作系统管理信息的访问,是 JMX 的 Java 标准 API。
示例:
import java.lang.management.*;
public class JvmInfo {
public static void main(String[] args) {
// 获取运行时信息
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
System.out.println("JVM Name: " + runtimeBean.getVmName());
System.out.println("JVM Version: " + runtimeBean.getVmVersion());
System.out.println("Uptime (ms): " + runtimeBean.getUptime());
// 获取内存信息
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
System.out.println("\nHeap Memory Usage:");
System.out.println(" Used: " + heapUsage.getUsed() / 1024 / 1024 + " MB");
System.out.println(" Max: " + heapUsage.getMax() / 1024 / 1024 + " MB");
System.out.println(" Committed: " + heapUsage.getCommitted() / 1024 / 1024 + " MB");
// 获取线程信息
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
System.out.println("\nThread Count: " + threadBean.getThreadCount());
System.out.println("Daemon Thread Count: " + threadBean.getDaemonThreadCount());
}
}
JMX (Java Management Extensions)
JMX 是一个更强大的框架,允许你通过外部管理工具(如 VisualVM, JConsole, 或自定义的客户端)来监控和管理正在运行的 Java 应用。
如何暴露 MBean:
- MBean 接口:定义一个接口,名称以
MBean- MBean 实现:实现该接口。
- 注册 MBean:使用
MBeanServer将你的 MBean 实现注册到 JVM 中。
示例:
// 1. MBean 接口
public interface HelloMBean {
String getName();
void setName(String name);
int getCacheSize();
void setCacheSize(int size);
void sayHello();
}
// 2. MBean 实现
public class Hello implements HelloMBean {
private String name;
private int cacheSize;
@Override
public String getName() { return name; }
@Override
public void setName(String name) { this.name = name; }
@Override
public int getCacheSize() { return cacheSize; }
@Override
public void setCacheSize(int size) {
this.cacheSize = size;
System.out.println("Cache size now set to: " + this.cacheSize);
}
@Override
public void sayHello() {
System.out.println("Hello, " + name + "!");
}
}
// 3. 注册 MBean
public class JmxAgent {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=Hello");
Hello mbean = new Hello();
mbs.registerMBean(mbean, name);
System.out.println("Waiting for JMX client...");
Thread.sleep(Long.MAX_VALUE);
}
}
启动后,你可以用 VisualVM 或 JConsole 连接到这个 JVM,在 MBeans 标签页下找到 com.example -> Hello,就可以调用其方法、查看属性了。
总结与实战建议
| 工具/命令 | 主要用途 | 优点 | 缺点 |
|---|---|---|---|
jps |
快速查找 Java 进程 ID | 简单快速 | 信息量少 |
jstat |
实时监控 GC 和内存使用 | 对性能影响小,数据实时 | 需要手动解析文本数据 |
jmap |
生成堆快照,查看对象分布 | 是内存泄漏分析的起点 | 生成堆快照会导致应用 Stop-the-World |
jstack |
生成线程快照,分析死锁/CPU问题 | 定位线程问题的利器 | 快照是瞬间的,可能抓不到问题 |
jcmd |
多功能命令,替代多个旧工具 | 功能强大,是未来的趋势 | 命令参数较多 |
| VisualVM | 全面的图形化监控 | 界面直观,功能集成度高 | 本地性能开销稍大 |
| Eclipse MAT | 深度分析堆转储文件 | 自动检测泄漏,功能最强大 | 需要学习使用,分析文件大时慢 |
| JConsole | 基础的图形化监控 | 轻量,随 JDK 安装 | 功能有限 |
| JMX API | 在应用中集成监控 | 灵活,可扩展,支持远程管理 | 需要编写代码 |
实战流程建议:
-
发现问题:应用响应慢、CPU 占用高、频繁 Full GC。
- 使用
top或htop找到占用 CPU 高的 Java 进程的 PID。 - 使用
jcmd <pid> Thread.print或 VisualVM 查看线程,定位是哪个线程在消耗 CPU。 - 使用
jcmd <pid> GC.heap_info或 VisualVM 的 Visual GC 窗口,观察 GC 频率和耗时。
- 使用
-
定位内存问题:怀疑内存泄漏(内存持续增长,OOM)。
- 使用
jcmd <pid> GC.class_histogram或 VisualVM 的 Sampler,观察对象数量是否异常。 - 在问题发生前或发生时,使用
jcmd <pid> GC.heap_dump <file.hprof>生成堆快照。 - 使用 Eclipse MAT 打开
.hprof文件,生成 Leak Suspects Report,直接定位泄漏根源。
- 使用
-
持续监控:在生产环境进行常态化监控。
- 在应用中集成 Micrometer、Dropwizard Metrics 等库,将 JVM 指标(GC、内存、线程)暴露给 Prometheus/Grafana 等监控系统。
- 利用 JMX,通过编写自定义的 MBean 来暴露业务关键指标。
