十、JVM 监控及诊断工具 - 命令行篇
JVM 的命令工具都存放在 jdk 的bin 目录下;
1、jps:查看正在运行的 Java 进程
显示指定系统内所有 HotSpot 虚拟机进程
语法:
jps [-l | -v]
-l: 详细的进程名称
-v: 虚拟机的参数
* 如果程序参数中添加了 -xx:UsePerfData 参数,命令就无法查询该程序的进程号
2、jstat:查看 JVM 统计信息
用于监视虚拟机各种运行状态信息;它可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。
语法:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
<optiopn>:
* class: 显示 ClassLoader 的相关信息: 类装载、占用空间、卸载数量、卸载类大小、装载类所消耗的时间。
gc 相关 ↓
* gc: 显示与 GC 相关的堆信息。
* gccapacity: 显示内容与 -gc 基本相同,但输出主要关注 Java 堆各个区域使用的最大、最小空间。
* gcutil: 显示内容与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比。
* gccause: 与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生 GC 产生的原因。
* gcnew: 显示新生代 GC 状况。
* gcnewcapacity: 显示内容与 -gcnew 基本相同,输出主要关注使用到的最大、最小空间。
* gcold: 显示老年代 GC 状况。
* gcoldcapacity: 显示内容与 -gcold 基本相同,输出主要关注使用到的最大、最小空间
* gcpermcapacity: 显示永久代使用到的最大、最小空间
JIT 相关 ↓
* compiler: 显示 JIT 编译器编译过的方法、耗时等信息
* printcompilation: 显示已经被 JIT编译过的方法
-t: 进程运行的时间
-h<lines>: 在周期性输出数据时,每隔多少行,就输出一个表头
<vmid>: 进程id
<interval>:
查询间隔,位为毫秒
<count>:
查询总次数(和 interval 搭配使用)
jstat -gc -t 命令的表格表头:
表头 | 含义(字节) |
EC | Eden区的大小 |
EU | Eden区已使用的大小 |
S0C | 幸存者0区的大小 |
S1C | 幸存者1区的大小 |
S0U | 幸存者0区已使用的大小 |
S1U | 幸存者1区已使用的大小 |
MC | 元空间的大小 |
MU | 元空间已使用的大小 |
OC | 老年代的大小 |
OU | 老年代已使用的大小 |
CCSC | 压缩类空间的大小 |
CCSU | 压缩类空间已使用的大小 |
YGC | 从应用程序启动到采样时young gc的次数 |
YGCT | 从应用程序启动到采样时young gc消耗时间(秒) |
FGC | 从应用程序启动到采样时full gc的次数 |
FGCT | 从应用程序启动到采样时的full gc的消耗时间(秒) |
GCT | 从应用程序启动到采样时gc的总时间 |
💡 如何使用 jstat -gc 来判断是否存在内存泄露:
1、在长时间运行的 Java 程序中,使用 jstat -gc 命令来连续获取多行 GC 内存数据,并取这几行数据列中 OU 列的最小值(即已占用的老年代内存);
2、每隔一段较长时间,重复上述操作,获取多组 OU 列最小值。如果这些值呈现上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此有可能存在内存泄露💡如何使用 jstat -gc -t 来判断堆压力:
我们可以比较 Java 进程的启动时间以及总 GC 时间(GCT列),或则两次测量时间的间隔时间以及总 GC 时间的增量,来得出 GC 时间占运行时间的比例,如果比例较高,说明堆压力大,如果接近 90 %,说明随时都有可能抛出 OOM。
3、jinfo:实时查看和修改 JVM 配置参数
查询虚拟机配置的参数信息,也可用于调整虚拟机的参数配置
语法:
jinfo [options] pid
[options]:
* no option: 不输入 option 时,会输出全部的参数和系统属性
* -flag name: 输出对应名称的参数
* -flag [+/-]name: 开启或关闭对应名称的参数,只有被标记为 manageable 的参数才可以被动态修改(针对的是 boolean 类型的参数)
* -flag name=value: 设定对应名称的参数(针对的是 值 类型的参数)
* -flags: 输出全部的参数
* -sysprops: 输出系统属性
------- 拓展 -------
命令:
java -XX:+PrintFlagsInitial: 查询所有 JVM 参数启动的初始值
java -XX:+PrintFlagsFinal: 查询所有 JVM 参数的最终值
java -XX:+PrintCommandLineFlags: 查询已经被用户或者 JVM 设置过的详细的 XX 参数的名称和值
4、jmap:导出内存映像文件&内存使用情况
获取 dump 文件(堆转储快照的二进制文件)以及获取 Java 进程的内存相关信息,包括 Java 堆各区域的使用情况、堆中对象的统计信息、类加载信息等。(官网推荐用 jcmd
)
语法:
jmap [option] pid
jmap [option] <executable <core>>
jmap [option] [server_id@]<remote server IP or hostname>
[option]:
* -dump: 生成 dump 文件
* -finalizerinfo: 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象
* -heap: 输出整个堆空间的详细信息,包括 GC 的使用、堆配置信息,以及内存的使用信息等。
* -histo: 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
* -permstat: 以 ClassLoader 为统计口径输出永久代的内存状态信息
* -F: 当虚拟机进程对 -dump 选项没有任何响应时,强制执行生成 dump 文件
💡 导出内存映像文件(dump 文件)
jmap -dump 命令是将堆中所有存活对象导出到一个文件中,通常在写 Heap Dump 文件之前会触发一次 Full GC,所以 heap dump 文件里保存的都是 Full GC 后留下的对象信息:手动的方式:
jmap -dump:format=b,file=<filename.hprof> pid
jmap -dump:live,format=b,file=<filename.hprof> pid
例:jmap -dump:format=b,file=d:\1.hprof 17792
参数说明:
format=b 表示生成标准格式的 dump
:live 只保存内存中存活中的对象自动的方式:
当程序发生 OOM 退出系统时,会自动生成 dump 文件-XX:+HeapDumpOnOutOfMemoryError
:在程序发生 OOM 时,导出应用程序的当前堆快照;-XX:HeapDumpPath
:指定快照的保存位置
例:-Xmx100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\m.hprof
由于 jmap 将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap 需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。所以这可能导致基于该堆快照的分析结果存在偏差。
5、jhat:JDK 自带堆分析工具
用于跟 jmap 搭配使用,解析 jmap 生成的 dump 文件。
💡 jhat 命令在 JDK9 及之后中已经被删除,建议使用 VisualVM 代替
语法:
jhat <filename.hprof>
6、jstack:打印 JVM 中线程快照
用于生成虚拟机指定进程当前时刻的线程快照;主要用于定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部资源导致的长时间等待问题。
在 thread dump 中,主要留意以下几种状态
- 死锁,Deadlock
- 等待资源,Waiting on condition
- 等待获取监视器,Waiting on monitor entry
- 阻塞,Blocked
- 执行中,Runnable
- 暂停,Suspended
- 对象等待中,Object.wait() 或 TIMED_WAITING
- 停止,Parked
语法:
jstack [option] pid
[option]:
* -F: 当正常输出的请求不被响应时,强制输出线程堆栈
* -l: 除堆栈外,显示关于锁的附加信息
* -m: 如果调用本地方法的话,可以显示 C/C++ 的堆栈
例: jstack -l 17792
7、jcmd:多功能命令行
在 JDK7 之后,新增的命令工具,可以实现前面除了 jstat 之外所有命令的功能,如导出堆、内存使用、查看 Java 进程、导出线程信息、执行 GC、JVM 运行时间等。(jcmd 拥有 jmap 大部分功能,官网推荐用 jcmd)
语法:
jcmd -l 列出所有的JVM 进程,跟 jps 命令相同
jcmd pid help 列出所有支持的命令
jcmd pid [help 查出来的具体指令]
8、jstatd:远程主机信息收集
建立本地计算机与远程监控工具的通信