性能监控与故障处理工具

jdk 所使用的监控工具,主要都是由tools.jar的实现

JPS

主要作用:用来列出正在执行的虚拟机进程,并显示虚拟机执行的主类名称,以及这些进程在本地虚拟机唯一ID(与操作系统的PID一致),

1
2
3
4
常用参数:
-m 输出启动时的main参数
-v 输出启动时的jvm参数
-l 输出全类名,如果是jar包启动,输出jar路径

jstat

是用于监视虚拟机各种运行状态信息的命令行工具,可显示本地或远程的虚拟机进程的 类加载,内存,垃圾回收,JIT编译等运行数据
命令格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

options:
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation

参考:

https://blog.csdn.net/zhaozheng7758/article/details/8623549

jinfo

可以实时的查看和修改虚拟机的各项参数,jps -v也可以看到启动参数,但如果想看一些默认参数,可以使用 jinfo -flag 打印,还可以使用-sysprops选项把虚拟机进程的System.getProperties()的内容打印出来,-flag name=value修改一部分运行期可写的虚拟机参数值

jmap

可以打印memory dump文件,比较关键的一个工具,曾经面试被问过,但我那时候只知道+HeapDumpOnOutOfMemoryError 来打印dump
其实还有 +HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成dump文件,又或者在Linux系统下通过Kill-3命令发送进程退出信号“吓唬”一下虚拟机,也能拿到dump文件。
jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等

1
2
jmap -heap 来获得 堆内存情况,
jmap -dump:format=b,file=aaa.dump 18267 打印jvm堆快照文件

此处需要下载 hotspot对应的 debugInfo ,注意小版本也需要相等,

wget http://debuginfo.centos.org/7/x86_64/java-1.8.0-openjdk-debuginfo-1.8.0.212.b04-0.el7_6.x86_64.rpm

jhat

是一个用来分析jmap生成的内存dump文件的工具,但一般用不到,不如直接使用eclipse MAT

jstack

用来生成 当前的线程快照, 可以用来确认线程长时间停顿 死锁 占用CPU时间长的原因,会打印出所有的线程的运行状况,

问题:

我起了一个springboot的示例程序来观察内存,
使用jstat 查看到:

1
2
3
4
5
6
NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
5440.0 83968.0 9984.0 960.0 960.0 8064.0 10944.0 167936.0 19848.0 19848.0 0.0 1081344.0 35456.0 0.0 1048576.0 4480.0 80 2

top:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18267 wks 20 0 2242.5m 127.8m 13.0m S 0.0 13.1 0:54.99 java

问题在于 OGC + NGC + MC !=top 里看到的Java内存大小
19848+9984+35456 = 63.7578125‬M
这让我很困扰

Conclusion:
java进程占用的内存大小并不只是堆内存,且我们没有办法估算 Java 进程占用的RAM内存,因为有太多的因素,
比如 栈内存,对外内存,垃圾回收器的RS,

1
2
3
4
Total memory = Heap + Code Cache + Metaspace + Symbol tables +
Other JVM structures + Thread stacks +
Direct buffers + Mapped files +
Native Libraries + Malloc overhead + ...

参考:

https://stackoverflow.com/questions/53451103/java-using-much-more-memory-than-heap-size-or-size-correctly-docker-memory-limi