十、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的总时间

windows 查看所有的java进程 windows查看java进程命令_java

💡 如何使用 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> pidjmap -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:远程主机信息收集

建立本地计算机与远程监控工具的通信