JDK
本身自带了许多 JVM
调优监控工具,可以帮助我们查看 Java 应用程序的进程、线程、内存栈等信息。这些工具命令包括 jps、jstack、jmap、jhat
等等。
这些命令所在位置:
Linux
:安装完 JDK 后,这些命令工具会默认放在 /usr/bin/
下,直接使用即可;Windows
:在 Windows 下,这些命令工具在安装 Java 目录的 jdk_xxx/bin/ 目录下,比如 C:\Program Files\Java\jdk1.8.0_212\bin,如果想要在控制台上使用的话,可以将改路径添加到环境变量 Path 中。JPS
该命令用于打印输出当前 JVM 中运行的 Java 进程状态信息,命令格式为:
jps [options] [hostid]
options
:表示命令可选参数,支持以下选项:
-q
:仅显示 pid;-m
:查看进程 pid 及 main 方法参数;-l
:打印程序对应 JAR 文件所在的完整路径名;-v
:查看进程 pid 及 JVM 的参数;-h
:打印帮助信息;hostid
:表示主机地址(包含协议、主机名、端口、服务名称),如果没有给出则默认为本地主机;实例如下:
[user@localhost home]$ jps -v
1763 jar
1871 Jps -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64 -Xms8m
JSTACK
该命令用于查看指定 Java 进程 pid 的堆栈信息,命令格式为:
jstack [options] pid
可选参数:
-l
:长列表展示,打印锁的附加信息;-m
:打印 Java 和底层 C/C++ 框架的所有栈信息;-F
:没有响应的时候强制打印栈信息;实例如下:
[user@localhost home]$ jstack 1763
2022-02-28 18:21:45
Full thread dump OpenJDK 64-Bit Server VM (25.292-b10 mixed mode):
"http-nio-8888-Acceptor" #28 daemon prio=5 os_prio=0 tid=0x00007fedf8d9a000 nid=0x713 runnable [0x00007fedc69d6000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:421)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:249)
- locked <0x00000000f864cb60> (a java.lang.Object)
以上只是堆栈信息的一部分内容,从内容中可以看到线程的运行状态为 RUNNABLE,线程的运行状态有如下几种:
JMAP
该命令用于查看堆内存的使用情况,一般与 jhat
结合一起使用,命令格式为:
jmap [option] pid
可选参数:
-heap
:查看进程堆内存使用情况,包括使用的 GC 算法、堆配置参数和各代中堆内存使用情况;-histo[:live]
:查看堆内存中的对象数目、大小统计直方图,如果带上 live 则只统计活对象;-dump:format=b,file=dumpFileName
:把进程内存使用情况 dump 到文件中;实例如下:
查看堆内存情况:
[user@localhost home]$ jmap -heap 2003
Attaching to process ID 2003, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.292-b10
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 132120576 (126.0MB)
NewSize = 2752512 (2.625MB)
MaxNewSize = 44040192 (42.0MB)
查看堆中对象数量:
[user@localhost home]$ jmap -histo 2003 | more
num #instances #bytes class name
----------------------------------------------
1: 46284 4602680 [C
2: 8592 1750048 [I
3: 46197 1108728 java.lang.String
4: 8416 928232 java.lang.Class
5: 10368 912384 java.lang.reflect.Method
6: 7634 898224 [B
7: 25961 830752 java.util.concurrent.ConcurrentHashMap$Node
8: 12156 486240 java.util.LinkedHashMap$Entry
9: 6483 441904 [Ljava.util.HashMap$Node;
生成 dump 文件:
[user@localhost home]$ jmap -dump:format=b,file=/home/dump.bat 2003
Dumping heap to /home/dump.bat ...
Heap dump file created
JHAT
该命令用于访问 Jmap 命令生成的 dump 文件,使用浏览器访问,命令格式为:
jhat [options] <heap-dump-file>
常用可选参数:
-port
:指定 Jhat 的 HTTP 服务端口,默认为 7000;实例如下:
[usr@localhost home]$ jhat -port 7000 dump.bat
Reading from dump.bat...
Dump file created Mon Feb 28 19:36:58 CST 2022
Snapshot read, resolving...
Resolving 349828 objects...
Chasing references, expect 69 dots..........................................................
Eliminating duplicate references....................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
然后在浏览器中输入地址:localhost:7000
(IP地址以运行 Jhat 命令所在服务地址为准):
JSTAT
该命令用于统计监测 JVM,命令格式为:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
其中:
vmid
:为虚拟机 ID,在 Linux/Unix 系统上一般就是进程 ID;interval
:为采样时间间隔;count
:为采样数;比如,下面命令为打印 GC 信息,采样时间间隔为 250ms,采样数为 3:
[user@localhost home]$ jstat -gc 2003 250 4
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1408.0 1408.0 0.0 0.0 11648.0 559.7 28776.0 17264.4 42752.0 40205.1 5632.0 5149.9 172 0.399 5 0.318 0.717
1408.0 1408.0 0.0 0.0 11648.0 559.7 28776.0 17264.4 42752.0 40205.1 5632.0 5149.9 172 0.399 5 0.318 0.717
1408.0 1408.0 0.0 0.0 11648.0 559.7 28776.0 17264.4 42752.0 40205.1 5632.0 5149.9 172 0.399 5 0.318 0.717
以上各列的含义为:
我们需要明白关于 JVM 堆内存的布局关系: