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
15jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
options:
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
参考:
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 | jmap -heap 来获得 堆内存情况, |
此处需要下载 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 | NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC |
问题在于 OGC + NGC + MC !=top 里看到的Java内存大小
19848+9984+35456 = 63.7578125M
这让我很困扰
Conclusion:
java进程占用的内存大小并不只是堆内存,且我们没有办法估算 Java 进程占用的RAM内存,因为有太多的因素,
比如 栈内存,对外内存,垃圾回收器的RS,1
2
3
4Total memory = Heap + Code Cache + Metaspace + Symbol tables +
Other JVM structures + Thread stacks +
Direct buffers + Mapped files +
Native Libraries + Malloc overhead + ...
参考: