在 Java 开发过程中,性能监控和问题排查是开发者经常面临的任务。JDK 提供了一系列命令行工具,帮助开发者监控 JVM 运行状态、诊断内存泄漏、线程死锁等问题。本文将详细介绍这些工具的使用方法及其应用场景。
1 JDK性能监控工具
1.1 jps:查看虚拟机进程
jps(Java Virtual Machine Process Status Tool)是 JDK 提供的一个命令行工具,用于快速查看当前系统中正在运行的 Java 应用及其进程 ID(PID)。它的功能类似于 Linux 下的 ps 命令,但专门针对 Java 进程。通过 jps,开发者可以快速获取 Java 进程的 PID,从而为后续使用其他 JVM 工具(如 jstack、jmap 等)进行诊断提供便利。
1.1.1 命令格式
bash
jps [options] [hostid]
options:可选参数,用于控制输出内容。hostid:可选参数,用于指定远程主机的标识符(通常用于远程监控)。
命令示例
运行 jps 命令后,输出结果可能如下:
bash
12345 MainClass
67890 AnotherApp
54321 SpringBootApp
- 每一行输出包含两部分:进程 ID(PID) 和 主类名称。
- 例如,
54321 SpringBootApp表示 PID 为54321的进程正在运行一个名为SpringBootApp的 Java 应用。
1.1.2 PID 的作用
-
PID(Process ID) 是操作系统分配给每个进程的唯一标识符。
-
通过 PID,开发者可以查看进程的详细信息,或者使用
kill命令终止进程。 -
例如,强制终止 PID 为
54321的进程:bashkill -9 54321注意 :
kill -9会强制终止进程,可能导致数据丢失或应用异常退出,生产环境中需谨慎使用。
1.1.3 常用选项
| 选项 | 描述 |
|---|---|
-q |
只输出进程 ID,忽略主类信息。 |
-l |
输出主类的全名,如果进程是通过 JAR 包启动的,则输出 JAR 文件的完整路径。 |
-m |
输出虚拟机进程启动时传递给主类 main() 方法的参数。 |
-v |
输出虚拟机进程启动时的 JVM 参数。 |
示例用法
-
查看所有 Java 进程及其主类全名:
bashjps -l输出示例:
bash12345 com.example.MainClass 67890 /path/to/AnotherApp.jar -
查看 Java 进程的 JVM 启动参数:
bashjps -v输出示例:
bash12345 MainClass -Xms512m -Xmx1024m -
只查看 Java 进程的 PID:
bashjps -q输出示例:
bash12345 67890
1.2 jstat:查看 JVM 运行时信息
jstat(Java Virtual Machine Statistics Monitoring Tool)是 JDK 提供的一个命令行工具,用于监控 JVM 的各种运行时状态信息。它能够提供关于垃圾回收、类加载、JIT 编译等方面的详细数据,帮助开发者分析和优化 Java 应用的性能。
1.2.1 命令格式
bash
jstat [option vmid [interval[s|ms] [count]]]
option:指定监控的类别,例如类加载、垃圾回收等。vmid:目标 Java 进程的进程 ID(PID)。interval:采样间隔时间,单位为秒(s)或毫秒(ms)。count:采样次数。
1.2.2 主要选项
jstat 的选项主要分为三类:类加载、垃圾回收、运行期编译状况。以下是常用选项及其功能:
1. -class:监视类加载信息
用于监控类的加载、卸载数量、总空间以及类加载所耗费的时间。
命令示例:
bash
jstat -class -t 75952 1000 2
输出示例:
bash
Loaded Bytes Unloaded Bytes Time
5000 10.5 MB 100 0.2 MB 1.23s
5100 10.8 MB 110 0.3 MB 1.45s
字段说明:
Loaded:加载的类的数量。Bytes:所有加载类占用的空间大小。Unloaded:卸载的类的数量。Time:类加载器所花费的时间。
2. -gc:监视 Java 堆状况
用于监控 Java 堆的各个区域(Eden 区、Survivor 区、老年代等)的容量、已用空间以及垃圾回收的时间和次数。
命令示例:
bash
jstat -gc 75952 1000 2
输出示例:
bash
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 1024.0 20480.0 1024.0 4480.0 2560.0 384.0 256.0 1 0.005 0 0.000 0.005
1024.0 1024.0 0.0 0.0 8192.0 2048.0 20480.0 1024.0 4480.0 2560.0 384.0 256.0 1 0.005 0 0.000 0.005
字段说明:
S0C、S1C:Survivor 0 区和 Survivor 1 区的当前容量(Current)。S0U、S1U:Survivor 0 区和 Survivor 1 区的已使用空间(Used)。EC、EU:Eden 区的容量和已使用空间。OC、OU:老年代的容量和已使用空间。MC、MU:元空间(Metaspace)的容量和已使用空间。YGC、YGCT:年轻代垃圾回收的次数和总时间。FGC、FGCT:老年代垃圾回收(Full GC)的次数和总时间。GCT:垃圾回收的总时间。
3. -compiler:监视 JIT 编译信息
用于监控 JIT(Just-In-Time)编译器编译过的方法、耗时等信息。
命令示例:
bash
jstat -compiler 75952 1000 2
输出示例:
bash
Compiled Failed Invalid Time FailedType FailedMethod
1000 10 5 1.23s SomeClass someMethod
1050 12 6 1.45s AnotherClass anotherMethod
字段说明:
Compiled:编译的方法数量。Failed:编译失败的方法数量。Invalid:失效的编译方法数量。Time:编译所花费的时间。
1.2.3 其他常用选项
| 选项 | 描述 |
|---|---|
-gccapacity |
监控 Java 堆各个区域的最大、最小空间。 |
-gcutil |
监控 Java 堆各个区域的已使用空间占总空间的百分比。 |
-gccause |
与 -gcutil 功能相同,但额外输出导致上一次垃圾回收的原因。 |
-gcnew |
监控新生代垃圾回收情况。 |
-gcnewcapacity |
监控新生代的最大、最小空间。 |
-gcold |
监控老年代垃圾回收情况。 |
-gcoldcapacity |
监控老年代的最大、最小空间。 |
-printcompilation |
输出已经被 JIT 编译的方法。 |
1.3 jinfo:查看虚拟机配置
jinfo(Configuration Info for Java)是 JDK 提供的一个命令行工具,用于查看或动态调整 JVM 的各项配置参数。它的主要功能包括:
- 查看 JVM 参数:输出当前 Java 进程的 JVM 启动参数。
- 动态修改参数:在不重启应用的情况下,调整某些 JVM 参数(仅限于支持动态修改的参数)。
1.3.1 命令格式
bash
jinfo [option] pid
option:可选参数,用于指定操作类型。pid:目标 Java 进程的进程 ID。
1.3.2 常用选项
| 选项 | 描述 |
|---|---|
-flags |
输出 JVM 的启动参数。 |
-sysprops |
输出 Java 系统属性(等同于 System.getProperties())。 |
-flag <name> |
查看某个特定 JVM 参数的值。 |
| `-flag [+ | -]<name>` |
1.3.3 示例用法
-
查看 JVM 启动参数:
bashjinfo -flags 88952输出示例:
bashAttaching to process ID 88952, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0.12+7-LTS Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 ... Command line: -Xms256m -Xmx4G -
查看 Java 系统属性:
bashjinfo -sysprops 88952输出示例:
bashAttaching to process ID 88952, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0.12+7-LTS java.runtime.name = Java(TM) SE Runtime Environment java.vm.version = 11.0.12+7-LTS user.country = CN ... -
查看特定 JVM 参数的值:
bashjinfo -flag MaxHeapSize 88952输出示例:
bash-XX:MaxHeapSize=4294967296 -
动态修改 JVM 参数:
bashjinfo -flag +PrintGCDetails 88952注意:并非所有 JVM 参数都支持动态修改,具体取决于 JVM 实现和参数类型。
1.3.4 常见问题及解决方法
问题:jinfo 命令无法执行成功,提示无法附加到进程。
可能原因:
- JDK 版本不一致:
jinfo工具的版本与目标 Java 进程使用的 JDK 版本不一致。 - 权限不足:当前用户没有权限访问目标进程。
- JDK 版本过旧:某些旧版本 JDK 可能存在兼容性问题。
解决方法:
-
确保 JDK 版本一致:
- 使用与目标 Java 进程相同的 JDK 版本的
jinfo工具。 - 例如,如果目标进程使用 JDK 11,则确保
jinfo也来自 JDK 11。
- 使用与目标 Java 进程相同的 JDK 版本的
-
使用管理员权限运行:
-
在 Linux/macOS 上,尝试使用
sudo提升权限:bashsudo jinfo -flags <pid>
-
-
升级 JDK 版本:
- 如果使用的是较旧的 JDK 版本,尝试升级到较新的稳定版本(如 JDK 11 或 JDK 17)。
示例:
bash
# 使用 JDK 11 的 jinfo 查看进程信息
/usr/lib/jvm/jdk-11/bin/jinfo -flags 10025
1.4 jmap:导出堆快照
jmap(Java Memory Map)是 JDK 提供的一个命令行工具,用于生成 Java 堆转储快照(heap dump),并查看堆内存的详细信息。堆转储文件包含了 JVM 堆中所有对象的信息,包括类、属性、引用等,是分析内存泄漏和优化内存使用的重要工具。
1.4.1 命令格式
bash
jmap [option] vmid
option:指定操作类型。vmid:目标 Java 进程的进程 ID(PID)。
1.4.2 常用选项
| 选项 | 描述 |
|---|---|
-dump |
生成 Java 堆转储快照(heap dump)。 |
-finalizerinfo |
显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象。(仅限 Linux 平台) |
-heap |
显示 Java 堆的详细信息,包括垃圾回收器类型、参数配置、分代情况等。(仅限 Linux 平台) |
-histo |
显示堆中对象的统计信息,包括类、实例数量、占用内存大小等。 |
-F |
当目标进程对 -dump 选项无响应时,强制生成堆转储快照。(仅限 Linux 平台) |
1.4.3 示例用法
-
生成堆转储快照:
bashjmap -dump:format=b,file=heap.hprof 10025format=b:指定文件格式为二进制。file=heap.hprof:指定输出文件名为heap.hprof。10025:目标 Java 进程的 PID。
说明:
- 生成的堆转储文件(
heap.hprof)可以使用工具(如 Eclipse MAT、VisualVM)进行分析。
-
查看堆中对象统计信息:
bashjmap -histo 10025输出示例:
bashnum #instances #bytes class name --------------------------------------------- 1: 100000 10000000 java.lang.String 2: 50000 2000000 java.util.HashMap$Node 3: 30000 1200000 java.lang.Object ...#instances:类的实例数量。#bytes:实例占用的内存大小。class name:类名。
-
显示 Java 堆详细信息:
bashjmap -heap 10025输出示例:
bashAttaching to process ID 10025, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0.12+7-LTS using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 4294967296 (4096.0MB) NewSize = 10485760 (10.0MB) MaxNewSize = 4294967296 (4096.0MB) OldSize = 20971520 (20.0MB) NewRatio = 2 SurvivorRatio = 8 ... -
强制生成堆转储快照:
bashjmap -F -dump:format=b,file=heap.hprof 10025- 当目标进程无响应时,使用
-F选项强制生成堆转储。
- 当目标进程无响应时,使用
1.4.4 堆转储文件分析工具
生成的堆转储文件(如 heap.hprof)可以使用以下工具进行分析:
-
Eclipse MAT(Memory Analyzer Tool):
- 功能强大,支持内存泄漏分析、对象依赖关系查看等。
- 下载地址:Eclipse MAT
-
VisualVM:
- JDK 自带的图形化工具,支持堆转储分析和性能监控。
- 启动命令:
jvisualvm
-
JProfiler:
- 商业工具,提供全面的性能分析和堆转储分析功能。
- 官网:JProfiler
1.5 jstack:跟踪 Java 堆栈
jstack 是 JDK 提供的一个命令行工具,用于打印 JVM 中某个进程的线程堆栈信息(通常称为 threaddump 或 javacore 文件)。它常用于诊断应用程序中的线程问题,如线程死锁、死循环或长时间等待。
1.5.1 命令格式
bash
jstack [option] vmid
option:可选参数,用于控制输出内容。vmid:目标 Java 进程的进程 ID(PID)。
1.5.2 常用选项
| 选项 | 描述 |
|---|---|
-F |
当正常输出的请求不被响应时,强制输出线程堆栈。 |
-l |
除了堆栈信息外,显示关于锁的附加信息(如持有的锁、等待的锁等)。 |
-m |
如果调用的是本地方法(Native Method),显示 C/C++ 的堆栈信息。 |
1.5.3 示例用法
-
打印线程堆栈信息:
bashjstack 10025输出示例:
bash"main" #1 prio=5 os_prio=0 tid=0x00007f8b4c009000 nid=0x2703 waiting on condition [0x00007f8b4d0f0000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076b70c4b8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.example.DeadLockDemo.lambda$main$0(DeadLockDemo.java:10) at com.example.DeadLockDemo$$Lambda$1/1096979270.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) -
打印线程堆栈信息及锁信息:
bashjstack -l 10025输出示例:
bash"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f8b4c0b8000 nid=0x2705 waiting for monitor entry [0x00007f8b4b6f0000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.DeadLockDemo.lambda$main$1(DeadLockDemo.java:25) - waiting to lock <0x000000076b70c4b8> (a java.lang.Object) - locked <0x000000076b70c4c8> (a java.lang.Object) at com.example.DeadLockDemo$$Lambda$2/1324119927.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Thread-0" #11 prio=5 os_prio=0 tid=0x00007f8b4c0b7000 nid=0x2704 waiting for monitor entry [0x00007f8b4b7f0000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.DeadLockDemo.lambda$main$0(DeadLockDemo.java:15) - waiting to lock <0x000000076b70c4c8> (a java.lang.Object) - locked <0x000000076b70c4b8> (a java.lang.Object) at com.example.DeadLockDemo$$Lambda$1/1096979270.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) -
强制打印线程堆栈信息:
bashjstack -F 10025- 当目标进程无响应时,使用
-F选项强制输出线程堆栈。
- 当目标进程无响应时,使用
1.5.4 诊断死锁问题
以下是一个简单的死锁示例程序:
java
class DeadLockDemo {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock1) {
System.out.println("线程1获取到了锁1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("线程1获取到了锁2");
}
}
}).start();
new Thread(() -> {
synchronized (lock2) {
System.out.println("线程2获取到了锁2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("线程2获取到了锁1");
}
}
}).start();
}
}
运行结果:
程序运行后卡住,无法继续执行。
使用 jstack 诊断死锁:
bash
jstack -l <pid>
输出示例:
bash
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f8b4c0b8000 (object 0x000000076b70c4b8, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007f8b4c0b7000 (object 0x000000076b70c4c8, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.example.DeadLockDemo.lambda$main$1(DeadLockDemo.java:25)
- waiting to lock <0x000000076b70c4b8> (a java.lang.Object)
- locked <0x000000076b70c4c8> (a java.lang.Object)
at com.example.DeadLockDemo$$Lambda$2/1324119927.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.example.DeadLockDemo.lambda$main$0(DeadLockDemo.java:15)
- waiting to lock <0x000000076b70c4c8> (a java.lang.Object)
- locked <0x000000076b70c4b8> (a java.lang.Object)
at com.example.DeadLockDemo$$Lambda$1/1096979270.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
说明:
jstack输出了死锁的详细信息,包括哪些线程在等待哪些锁,以及锁的持有者。
1.6 jcmd:多功能命令
jcmd 是 JDK 提供的一个多功能命令行工具,集成了 jstack、jmap、jstat、jinfo 等工具的功能。它能够收集堆转储、生成 JVM 和 Java 应用程序的性能数据,以及动态更改某些 Java 运行时参数。jcmd 的强大之处在于它可以通过单一命令完成多种任务,简化了 JVM 监控和诊断的操作。
1.6.1 命令格式
bash
jcmd <pid | main class> <command ... | PerfCounter.print | -f file>
pid:目标 Java 进程的进程 ID。main class:目标 Java 应用的主类名。command:要执行的操作或命令。PerfCounter.print:打印性能计数器信息。-f file:从文件中读取命令并执行。
1.6.2 常用功能
-
列出所有 Java 应用:
bashjcmd -l输出示例:
java10025 com.example.MainClass 20036 org.apache.catalina.startup.Bootstrap -
查看支持的命令:
bashjcmd 10025 help输出示例:
javaThe following commands are available: JFR.stop JFR.start JFR.dump JFR.check VM.native_memory VM.check_commercial_features VM.unlock_commercial_features ManagementAgent.stop ManagementAgent.start_local ManagementAgent.start Thread.print GC.class_histogram GC.heap_dump GC.run_finalization GC.run VM.uptime VM.flags VM.system_properties VM.command_line VM.version help -
查看 JVM 参数:
bashjcmd 10025 VM.flags输出示例:
bash-XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 ... -
打印线程信息:
bashjcmd 10025 Thread.print输出示例:
bash"main" #1 prio=5 os_prio=0 tid=0x00007f8b4c009000 nid=0x2703 waiting on condition [0x00007f8b4d0f0000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076b70c4b8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.example.DeadLockDemo.lambda$main$0(DeadLockDemo.java:10) at com.example.DeadLockDemo$$Lambda$1/1096979270.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) -
生成堆转储文件:
bashjcmd 10025 GC.heap_dump filename=heap.hprof说明:
- 生成的堆转储文件(
heap.hprof)可以使用工具(如 Eclipse MAT、VisualVM)进行分析。
- 生成的堆转储文件(
-
打印性能计数器信息:
bashjcmd 10025 PerfCounter.print输出示例:
bashjava.ci.totalTime=123456 java.cls.loadedClasses=5000 java.cls.unloadedClasses=100 ... -
查看系统属性:
bashjcmd 10025 VM.system_properties输出示例:
bashjava.runtime.name=Java(TM) SE Runtime Environment java.vm.version=11.0.12+7-LTS user.country=CN ... -
查看 JVM 启动时间:
bashjcmd 10025 VM.uptime输出示例:
bash1234.567 seconds
1.6.3 主要选项
| 选项 | 描述 | 补充说明 |
|---|---|---|
help |
打印帮助信息。 | 示例:jcmd help |
ManagementAgent.stop |
停止 JMX Agent。 | |
ManagementAgent.start_local |
开启本地 JMX Agent。 | |
ManagementAgent.start |
开启 JMX Agent。 | |
Thread.print |
打印线程信息,相当于 jstack。 |
支持 -l 参数打印锁信息。 |
PerfCounter.print |
打印性能计数器信息,相当于 jstat -J-Djstat.showUnsupported=true -snap。 |
|
GC.class_histogram |
打印堆中对象统计信息,相当于 jmap -histo。 |
|
GC.heap_dump |
生成堆转储文件,相当于 jmap -dump:format=b,file=xxx.bin。 |
|
GC.run_finalization |
运行 finalize 方法,相当于 System.runFinalization()。 |
|
GC.run |
触发垃圾回收,相当于 System.gc()。 |
|
VM.uptime |
打印 JVM 启动时间,以秒为单位。 | 支持 -date 参数打印当前时间。 |
VM.flags |
打印 JVM 参数,相当于 jinfo -flags。 |
支持 -all 参数输出全部信息。 |
VM.system_properties |
打印系统属性,相当于 jinfo -sysprops。 |
|
VM.command_line |
打印 JVM 启动命令,相当于 `jinfo -sysprops | grep command`。 |
VM.version |
打印 JVM 版本信息,相当于 `jinfo -sysprops | grep version`。 |
2 操作系统工具
除了 JDK 自带的工具,操作系统也提供了一些命令行工具,帮助开发者监控系统资源使用情况。
2.1 top:显示系统整体资源使用情况
top 是一个常用的命令行工具,用于实时监控系统的整体资源使用情况,包括 CPU、内存、进程等。它能够帮助开发者快速识别系统中占用资源较高的进程,从而进行性能分析和优化。
2.1.1 命令格式
bash
top
- 默认情况下,
top会实时更新显示信息,按Ctrl + C退出。
2.1.2 输出解析
top 的输出分为两部分:统计信息 和进程信息。
1. 统计信息
统计信息部分提供了系统的整体资源使用情况,主要包括以下内容:
-
进程和线程信息:
bashProcesses: 500 total, 10 running, 490 sleeping, 2000 threadsProcesses:总进程数。running:正在运行的进程数。sleeping:睡眠的进程数。threads:总线程数。
-
负载均衡和 CPU 使用率:
bashLoad Avg: 4.02, 3.89, 3.29 CPU usage: 6.97% user, 3.54% sys, 89.47% idleLoad Avg:过去 1 分钟、5 分钟和 15 分钟的平均系统负载。负载值大于 CPU 核心数时,表示系统相对繁忙。CPU usage:user:用户进程占用的 CPU 百分比。sys:系统内核占用的 CPU 百分比。idle:CPU 空闲百分比。
-
共享库内存使用:
bashSharedLibs: 100M resident, 50M data, 10M linkedit.- 显示操作系统加载的共享库(如动态链接库)的内存使用情况。
-
内存区域使用:
bashMemRegions: 5000 total, 100M resident, 50M private, 200M shared.- 显示系统内存区域的使用情况,包括代码、数据、堆、栈等。
-
物理内存使用:
bashPhysMem: 30G used (3018M wired), 1547M unused.used:已使用的物理内存。wired:被锁定在内存中的部分(不可被交换到磁盘)。unused:未使用的物理内存。
-
虚拟内存信息:
bashVM: 50G vsize, 20G framework vsize, 10G swapins, 5G swapouts.vsize:虚拟内存总量。swapins:从磁盘交换到内存的数据量。swapouts:从内存交换到磁盘的数据量。
-
网络和硬盘信息:
bashNetworks: packets: 22655692/19G in, 19180791/11G out. Disks: 14866544/288G read, 15176739/251G written.Networks:网络接收和发送的数据包数量及大小。Disks:硬盘读取和写入的次数及数据量。
2. 进程信息
进程信息部分列出了系统中各个进程的资源使用情况,主要字段包括:
| 字段 | 描述 |
|---|---|
PID |
进程 ID,是操作系统分配给进程的唯一标识符。 |
COMMAND |
进程的命令名或命令行。 |
%CPU |
进程占用的 CPU 使用率。 |
TIME |
进程使用的 CPU 时间总计,单位为 1/100 秒。 |
MEM |
进程使用的物理内存和虚拟内存大小,单位为 KB。 |
示例:
bash
PID COMMAND %CPU TIME MEM
10025 java 10.5 00:10.23 1024M
20036 chrome 5.2 00:05.12 512M
2.1.3 常用操作
-
按 CPU 使用率排序:
- 运行
top后,按P键。
- 运行
-
按内存使用率排序:
- 运行
top后,按M键。
- 运行
-
刷新间隔设置:
- 运行
top后,按d键,然后输入刷新间隔(秒)。
- 运行
-
退出
top:- 按
Ctrl + C或q键。
- 按
2.1.4 Windows 替代工具
在 Windows 系统中,可以使用以下命令查看进程信息:
-
tasklist:bashtasklist输出示例:
bashImage Name PID Session Name Session# Mem Usage ========================= ======== ================ =========== ============ java.exe 10025 Console 1 102,400 K chrome.exe 20036 Console 1 512,000 K -
任务管理器:
- 通过
Ctrl + Shift + Esc打开任务管理器,查看进程和资源使用情况。
- 通过
2.2 vmstat:监控内存和 CPU
vmstat(Virtual Memory Statistics)是 Linux 系统上的一款性能监控工具,用于统计系统的 CPU、内存、swap、I/O 等资源的使用情况。它能够帮助开发者快速了解系统的整体性能状况,识别资源瓶颈。
2.2.1 命令格式
bash
vmstat [options] [delay [count]]
options:可选参数,用于指定输出内容。delay:采样间隔时间,单位为秒。count:采样次数。
2.2.2 基本用法
-
实时监控:
bashvmstat 1 3- 每秒采样一次,共采样 3 次。
-
持续监控:
bashvmstat 1- 每秒采样一次,持续输出,按
Ctrl + C退出。
- 每秒采样一次,持续输出,按
2.2.3 输出解析
vmstat 的输出分为两部分:系统资源概览 和详细统计信息。
示例输出:
bash
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 100000 20000 300000 0 0 10 20 100 200 5 2 93 0 0
0 0 0 98000 21000 310000 0 0 15 25 110 210 6 1 93 0 0
字段说明:
-
procs(进程):
r:等待运行的进程数。b:处于不可中断睡眠状态的进程数。
-
memory(内存):
swpd:使用的虚拟内存大小(swap)。free:空闲的物理内存大小。buff:用作缓冲区的内存大小。cache:用作缓存的内存大小。
-
swap(交换分区):
si:每秒从磁盘读入 swap 的数据量(KB)。so:每秒写入磁盘的 swap 数据量(KB)。
-
io(I/O):
bi:每秒从块设备读入的数据量(KB)。bo:每秒写入块设备的数据量(KB)。
-
system(系统):
in:每秒的中断次数。cs:每秒的上下文切换次数。
-
cpu(CPU):
us:用户进程占用的 CPU 百分比。sy:系统内核占用的 CPU 百分比。id:CPU 空闲百分比。wa:等待 I/O 操作的 CPU 百分比。st:虚拟机占用的 CPU 百分比。
2.2.4 常用选项
| 选项 | 描述 |
|---|---|
-a |
显示活跃和非活跃内存。 |
-d |
显示磁盘统计信息。 |
-s |
显示内存统计信息。 |
-p |
显示指定分区的 I/O 统计信息。 |
-t |
在输出中增加时间戳。 |
示例用法
-
显示活跃和非活跃内存:
bashvmstat -a 1 3输出示例:
bashprocs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free inact active si so bi bo in cs us sy id wa st 1 0 0 100000 200000 300000 0 0 10 20 100 200 5 2 93 0 0 -
显示磁盘统计信息:
bashvmstat -d 1 3输出示例:
bashdisk- ------------reads------------ ------------writes----------- -----IO------ total merged sectors ms total merged sectors ms cur sec sda 1000 200 100000 500 500 100 50000 300 0 0 -
显示内存统计信息:
bashvmstat -s输出示例:
bash1000000 total memory 800000 used memory 200000 active memory 100000 inactive memory 50000 free memory -
显示指定分区的 I/O 统计信息:
bashvmstat -p /dev/sda1 1 3输出示例:
bashsda1 reads read sectors writes requested writes 1000 100000 500 50000
2.3 iostat:监控 IO 使用
iostat(Input/Output Statistics)是 Linux 系统上的一款性能监控工具,用于统计 CPU 使用情况和磁盘的 I/O 信息。它能够帮助开发者分析系统的 I/O 性能,识别磁盘瓶颈。
2.3.1 命令格式
bash
iostat [options] [interval [count]]
options:可选参数,用于指定输出内容。interval:采样间隔时间,单位为秒。count:采样次数。
2.3.2 输出解析
iostat 的输出分为两部分:CPU 使用情况 和磁盘 I/O 统计。
示例输出:
bash
Linux 5.4.0-42-generic (hostname) 09/01/2023 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.23 0.00 1.23 0.12 0.00 93.42
Device tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 1.23 10.00 20.00 100000 200000
字段说明:
-
CPU 使用情况:
%user:用户进程占用的 CPU 百分比。%nice:低优先级用户进程占用的 CPU 百分比。%system:系统内核占用的 CPU 百分比。%iowait:等待 I/O 操作的 CPU 百分比。%steal:虚拟机被其他虚拟机占用的 CPU 百分比。%idle:CPU 空闲百分比。
-
磁盘 I/O 统计:
tps:每秒传输次数(Transfers Per Second)。kB_read/s:每秒读取的数据量(KB)。kB_wrtn/s:每秒写入的数据量(KB)。kB_read:读取的总数据量(KB)。kB_wrtn:写入的总数据量(KB)。
2.3.3 常用选项
| 选项 | 描述 |
|---|---|
-c |
只显示 CPU 使用情况。 |
-d |
只显示磁盘 I/O 统计信息。 |
-x |
显示扩展的磁盘 I/O 统计信息。 |
-p |
显示指定磁盘分区的 I/O 统计信息。 |
-t |
在输出中增加时间戳。 |
示例用法
-
查看 CPU 和所有磁盘设备的基本 I/O 统计信息:
bashiostat输出示例:
bashavg-cpu: %user %nice %system %iowait %steal %idle 5.23 0.00 1.23 0.12 0.00 93.42 Device tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda 1.23 10.00 20.00 100000 200000 -
查看磁盘 I/O 统计信息,每 2 秒更新一次:
bashiostat -d 2输出示例:
bashDevice tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda 1.23 10.00 20.00 100000 200000 sda 1.50 15.00 25.00 150000 250000 -
查看扩展的磁盘 I/O 统计信息:
bashiostat -x输出示例:
bashDevice r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await svctm %util sda 0.50 0.73 10.00 20.00 0.00 0.00 0.00 0.00 1.23 2.34 0.56 0.12扩展字段说明:
r/s:每秒读取次数。w/s:每秒写入次数。rkB/s:每秒读取的数据量(KB)。wkB/s:每秒写入的数据量(KB)。rrqm/s:每秒合并的读取请求数。wrqm/s:每秒合并的写入请求数。%rrqm:读取请求合并的百分比。%wrqm:写入请求合并的百分比。r_await:读取请求的平均等待时间(毫秒)。w_await:写入请求的平均等待时间(毫秒)。svctm:I/O 请求的平均服务时间(毫秒)。%util:磁盘的繁忙程度(百分比)。
-
只查看 CPU 使用情况:
bashiostat -c输出示例:
bashavg-cpu: %user %nice %system %iowait %steal %idle 5.23 0.00 1.23 0.12 0.00 93.42 -
查看指定磁盘分区的 I/O 统计信息:
bashiostat -p sda1输出示例:
bashDevice tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda1 1.23 10.00 20.00 100000 200000
2.4 netstat:监控网络使用
netstat(Network Statistics)是一个常用的命令行工具,用于监控和显示网络相关信息,包括网络连接、路由表、接口统计等。它能够帮助开发者分析网络状态,诊断网络问题。
2.4.1 命令格式
bash
netstat [options]
options:可选参数,用于指定输出内容。
2.4.2 常用选项
| 选项 | 描述 |
|---|---|
-a |
显示所有连接和侦听端口。 |
-t |
显示 TCP 连接。 |
-u |
显示 UDP 连接。 |
-n |
以数字形式显示地址和端口号(不解析主机名和服务名)。 |
-r |
显示路由表。 |
-l |
显示侦听中的套接字。 |
-p |
显示与套接字关联的进程 ID 和程序名称。 |
-s |
显示网络协议的统计信息。 |
-c |
持续输出网络信息,按 Ctrl + C 退出。 |
2.4.3 输出解析
netstat 的输出通常包括以下几个方面的信息:
-
网络连接:
- 显示活动的或监听的套接字连接,包括协议、本地地址和端口、远程地址和端口、连接状态等。
-
路由表:
- 显示网络路由表,包括目的地址、网关、子网掩码、使用的接口等。
示例用法
-
显示所有连接和侦听端口:
bashnetstat -a输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 192.168.1.100:22 192.168.1.200:54321 ESTABLISHED udp 0 0 0.0.0.0:68 0.0.0.0:* -
显示 TCP 连接:
bashnetstat -t输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.1.100:22 192.168.1.200:54321 ESTABLISHED -
显示 UDP 连接:
bashnetstat -u输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State udp 0 0 0.0.0.0:68 0.0.0.0:* -
以数字形式显示地址和端口号:
bashnetstat -n输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.168.1.100:22 192.168.1.200:54321 ESTABLISHED -
显示路由表:
bashnetstat -r输出示例:
bashKernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 192.168.1.0 * 255.255.255.0 U 0 0 0 eth0 -
显示侦听中的套接字:
bashnetstat -l输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
显示与套接字关联的进程 ID 和程序名称:
bashnetstat -p输出示例:
bashProto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 192.168.1.100:22 192.168.1.200:54321 ESTABLISHED 1234/sshd -
显示网络协议的统计信息:
bashnetstat -s输出示例:
bashIp: 1000 total packets received 0 forwarded 0 incoming packets discarded 1000 incoming packets delivered 1000 requests sent out -
持续输出网络信息:
bashnetstat -c- 持续输出网络信息,按
Ctrl + C退出。
- 持续输出网络信息,按
3 总结
JDK 提供的性能监控工具和操作系统命令行工具是开发者排查问题、优化性能的利器。掌握这些工具的使用方法,能够帮助开发者在面对内存泄漏、线程死锁等问题时,快速定位并解决问题。希望本文的介绍能够为开发者提供有价值的参考。
4 思维导图
