JDK内置监控命令工具

179 阅读14分钟

引言

jdk提供了很多强大的工具有命令行也有可视化的,目的是可以让开发者去查看JVM信息以及监控JVM相关的内容

为了在实际工作中能够排查和解决JVM在生产环境发生的问题,所以有必要去学习了解这些优化工具

命令工具

javap

java反编译工具,主要用于根据java字节码文件反汇编为java源代码文件

用法:javap

指令描述
javap -help --help -?输出此用法消息
javap -version版本信息
javap -v -verbose输出附加信息
javap -l17.09
javap -public仅显示公共类和成员
javap -protected显示受保护/公共的类和成员
javap -package显示程序包/受保护/公共类和成员
javap -p -private显示所有类和成员
javap -c对代码进行反汇编
javap -s输出内部类型签名
javap -sysinfo显示正在处理的类的系统信息(路径,大小,日期,MD5散列)
javap -constants显示静态最终常量
Javap -classpath 指定查找用户类文件的位置
javap -bootclasspath 覆盖引导类文件的位置

这个命令是所有的java版本都支持的,包括一些版本号以及输出类的相关信息显示类的成员变量

当然我们最常用的还是javap -v -verbose命令因为它能够看到所有的内容比如说方法定义、字节码

image.png

jps

jps是用来查看当前java进程pid的

用法:jps

指令描述
jps -q仅输出VM标识符,不包括classname,jar,name,arguments in main method
jps -m输出main method的参数
jps -l输出完全的包名,应用主类名,jar的完全路径名
jsp -v输出jvm参数
jsp -V输出通过flag文件传递到jvm中的参数(.hostpotrc文件或-XX:Flags=所指定的文件)
jps -Joption传递参数到vm,例如:-J-Xms512m

image.png

jstat

jstat是平时在监控虚拟机时很常用的一个工具, 特别是在做jvm性能优化时对开发者起到很大的辅助作用

它可以输出GC的信息对GC时间做一些统计,比如说垃圾回收进行了多少次GC耗时是多少

包括说整个JVM里面加载了一些class的信息以及说每个class对应的实例数量和所占用的空间

用法:jstat [generalOption | outputOptions vmid [interval [s | ms] [count]]]

-t参数可以在输出信息前面加一个timestamp列显示程序的运行时间

-h参数可以在周期性的数据输出时,输出多少行数据后,跟着输出一个表头信息

interval指定输出统计周期,count指定输出多少次数据

指令描述
jstat -gc pid显示gc的信息,查看gc的次数及时间
jstat -gccapacity pid内存GC分区中各对象的使用和占用大小
jstat -gcutil pid统计gc信息
jstat -gcnew pid年轻代对象信息
jstat -gcnewcapacity pid年轻代对象的信息及其占用量
jstat -gcold pidold代对象的信息
jstat -gcoldcapacity pid老年代对象的信息及其占用量
jstat -gcmetacapacity pid元数据区内存分析
jstat -class pid显示加载class的数量,及所占用空间等信息
jstat -compiler pid显示VM实时编译的数据等信息
jstat -printcompilation pid当前VM执行的信息

-class 类加载统计

image.png

参数含义
Loaded加载类的数量
Bytes加载类的size,单位为Byte
Unloaded卸载类的数目
Time加载与卸载类花费的时间

-compiler 编译统计

image.png

参数含义
Compiled编译任务执行数量
Failed编译任务执行失败数量
Invalid编译任务执行失效数量
Time编译任务消耗时间
FailedType最后一个编译失败任务的类型
FailedMethod最后一个编译失败任务所在的类及方法

-gc 垃圾回收统计

image.png

参数名参数含义
S0C年轻代中第一个survivor(幸存区)的容量 (字节)
S1C年轻代中第二个survivor(幸存区)的容量 (字节)
S0U年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC年轻代中Eden(伊甸园)的容量 (字节)
EU年轻代中Eden(伊甸园)目前已使用空间 (字节)
OCOld代的容量 (字节)
OUOld代目前已使用空间 (字节)
MCmetaspace(元空间)的容量 (字节)
MUmetaspace(元空间)目前已使用空间 (字节)
CCSC当前压缩类空间的容量 (字节)
CCSU当前压缩类空间目前已使用空间 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
YGCT从应用程序启动到采样时年轻代中gc所用时间(s)
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)

-gccapacity 堆内存统计

image.png

参数含义
NGCMN年轻代(young)中初始化(最小)的大小(字节)
NGCMX年轻代(young)的最大容量 (字节)
NGC年轻代(young)中当前的容量 (字节)
S0C年轻代中第一个survivor(幸存区)的容量 (字节)
S1C年轻代中第二个survivor(幸存区)的容量 (字节)
EC年轻代中Eden(伊甸园)的容量 (字节)
OGCMNold代中初始化(最小)的大小 (字节)
OGCMXold代的最大容量(字节)
OGCold代当前新生成的容量 (字节)
OCOld代的容量 (字节)
MCMNmetaspace(元空间)中初始化(最小)的大小 (字节)
MCMXmetaspace(元空间)的最大容量 (字节)
MCmetaspace(元空间)当前新生成的容量 (字节)
CCSMN最小压缩类空间大小
CCSMX最大压缩类空间大小
CCSC当前压缩类空间大小
YGC从应用程序启动到采样时年轻代中gc次数
FGC从应用程序启动到采样时old代(全gc)gc次数

-gcmetacapacity 元数据空间统计

image.png

参数含义
MCMN最小元数据容量
MCMX最大元数据容量
MC当前元数据空间大小
CCSMN最小压缩类空间大小
CCSMX最大压缩类空间大小
CCSC当前压缩类空间大小
YGC从应用程序启动到采样时年轻代中gc次数
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)

-gcnew 新生代垃圾回收统计

image.png

参数含义
S0C年轻代中第一个survivor(幸存区)的容量 (字节)
S1C年轻代中第二个survivor(幸存区)的容量 (字节)
S0U年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
TT持有次数限制
MTT最大持有次数限制
DSS期望的幸存区大小
EC年轻代中Eden(伊甸园)的容量 (字节)
EU年轻代中Eden(伊甸园)目前已使用空间 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
YGCT从应用程序启动到采样时年轻代中gc所用时间(s)

-gcnewcapacity 新生代内存统计

image.png

参数含义
NGCMN年轻代(young)中初始化(最小)的大小(字节)
NGCMX年轻代(young)的最大容量 (字节)
NGC年轻代(young)中当前的容量 (字节)
S0CMX年轻代中第一个survivor(幸存区)的最大容量 (字节)
S0C年轻代中第一个survivor(幸存区)的容量 (字节)
S1CMX年轻代中第二个survivor(幸存区)的最大容量 (字节)
S1C年轻代中第二个survivor(幸存区)的容量 (字节)
ECMX年轻代中Eden(伊甸园)的最大容量 (字节)
EC年轻代中Eden(伊甸园)的容量 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
FGC从应用程序启动到采样时old代(全gc)gc次数

-gcold 老年代垃圾回收统计

image.png

参数含义
MCmetaspace(元空间)的容量 (字节)
MUmetaspace(元空间)目前已使用空间 (字节)
CCSC压缩类空间大小
CCSU压缩类空间使用大小
OCOld代的容量 (字节)
OUOld代目前已使用空间 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)

-gcoldcapacity 老年代内存统计

image.png

参数含义
OGCMNold代中初始化(最小)的大小 (字节)
OGCMXold代的最大容量(字节)
OGCold代当前新生成的容量 (字节)
OCOld代的容量 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)

-gcutil 垃圾回收统计

image.png

参数含义
S0年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E年轻代中Eden(伊甸园)已使用的占当前容量百分比
Oold代已使用的占当前容量百分比
M元数据区已使用的占当前容量百分比
CCS压缩类空间已使用的占当前容量百分比
YGC从应用程序启动到采样时年轻代中gc次数
YGCT从应用程序启动到采样时年轻代中gc所用时间(s)
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)

监控输出信息

image.png

-h代表 每隔多少行输出一次表头,1000代表每隔多少毫秒输出一次监控内容

jcmd

jcmd可以替代jps工具,对于查看本地jvm信息两者之间更多的是使用jcmd,因为jcmd可以让运行中的jvm执行相关指令

用法:jcmd <pid | main class> <command...|PerfCounter.print|-f file>

指令描述
jcmd查看本地的java进程,获取其pid
jcmd pid help查看其支持的命令列表
jcmd pid Thread.print -l打印线程栈
jcmd pid VM.command_line打印启动命令及参数
jcmd pid GC.heap_dump /data/filename.dump查看JVM的Heap Dump
jcmd pid GC.class_histogram查看类的统计信息
jcmd pid GC.system_properties查看系统属性内容
jcmd pid VM.uptime查看虚拟机启动时间
jcmd pid PerfCounter.print查看性能统计

image.png

jinfo

jinfo可以查看运行中的jvm的全部参数,还可以设置部分参数.可以去看本地运行中的jvm也可以去看远程的

用法:jinfo [option] pid、jinfo [option] executable core、jinfo [option] [server-id@] remote-hostname-or-IP

参数说明
pid对应jvm的进程id
executable core产生core dump文件
[server-id@] remote-hostname-or-IPserver-id标记服务唯一ID,远程的ip或者hostname
指令描述
no option输出全部的参数和系统属性
-flag name输出对应名称的参数
-flag [+-]name开启或关闭对应名称的参数
-flag name=value设定对应名称的参数
-flags输出全部的参数
-sysprops输出系统属性

image.png

jmp

打印出java进程内存中对象的情况,或者将VM中的堆以二进制输出成文本,这是我们在做内存溢出和泄露排查时经常用到的一个命令

用法:jmap [option] pid 、jmap [option] executable core、jmap [option] [server-id@] remote-hostname-or-IP

指令描述
no option打印目标jvm加载的每个共享对象的起始地址。映射大小及共享对象文件路径
-dump:[live] format=b,file=使用hprof二进制输出heap内容到文件live代表只输出存活对象
-flag [+-]name打印正等候回收的对象信息
-heap打印heap概要信息,GC使用算法,heap的配置及wise heap的使用情况
-histo:[]打印每个class的内存信息VM内部类会加上前缀“*”live代表只输出存活对象
-clstats打印classload详细信息和jvm heap方法区的信息
-F强迫在pid没有响应-dump或-histo的时候;这个模式下不支持live参数
-hhelp打印辅助信息
-J传递参数给jmap启动的jvm

image.png

image.png

生成内存快照文件dump.bin

jhat

java Head Analyse Tool分析java堆的命令,它的分析不是说把里面的内容给我们查出来,而是说将堆中的对象以html的形式显示出来,支持对象查询语言OQL

它是一个网页的服务可以根据需要定制化查看内容

jhat [-stack ] [-refs ] [-prot ] [-baseline ] [-debug ] [-version] [-h|-help]

指令描述
-J启动JVM时传入的启动参数,如-J-Xmx512m则指定jhat最大堆内存为512m
-stack falsetrue关闭对象分配调用栈跟踪.默认为true
-refs falsetrue关闭对象引用跟踪.默认为true
-port port-number设置jhat HTTP server的端口号 默认7000
-exclude exclude-file指定文件对象查询时需要排除的数据成员列表
-baseline exclude-file指定一个基准堆转储,在比较两个不同的堆转储时很有用
-debug int设置debug级别 0表示不输出调试信息 值越大则调试信息更详细
-version启动后只显示版本信息就退出

image.png

image.png

jstack

堆栈跟踪工具jstack用于打印出给定的java进程ID或core file或远程调试服务的java堆栈信息,如果是在64位机器上需要指定选项-J-d64

一般会在分析cpu100%和死锁的时候用到,查看当前jvm正在运行哪些线程这些线程的栈信息是什么情况

用法:jstack [option] pid、jstack [option] executable core、jstack [option] [server-id@] remote-hostname-or-IP

参数说明
pid对应jvm的进程id
executable core产生core dump文件
[server-id@] remote-hostname-or-IPserver-id标记服务唯一ID,远程的ip或者hostname
指令描述
-F强制打印栈信息
-l长列表;打印关于锁的附加信息
-m打印java和native c/c++框架的所有栈信息
-h-help打印帮助信息

image.png

在控制台中看jvm线程信息,有时候线程太多控制台不好看 可以输出到文件,以文件的形式进行观察

image.png

image.png

可视化工具

jconsole

这个可视化工具通常会在测试和性能调试的时候会用到,存放在jdk/bin 目录底下

image.png

image.png

概览中可以查看堆内存使用情况、线程活动情况、类加载卸载情况、CPU占用率

image.png

内存中可以查看堆、非堆、新生代、老年的、元数据、压缩类空间等内存池的使用情况

image.png

线程中可以查看线程的栈运行情况

image.png

类中可以看到类的加载情况

image.png

VM概要中查看当前JVM进程的一些概要信息:运行时参数、线程、内存、类加载

image.png

MBean中查看实现了Java管理扩展(jmx)的对象实例

image.png

jvisualvm

jvisualvm是java提供比较全面工具,它不仅可以监控运行时的JVM还可以分析dump内存快照

image.png

image.png

监视页面中查看CPU、堆、类、线程的活动情况

image.png

线程页面中查看线程的运行情况

image.png

点击线程dump可以查看每个线程栈的情况

image.png

抽样器页面可以实时查看每个线程占用CPU、内存情况

image.png image.png

查看堆内存快照文件

image.png

image.png

image.png

image.png image.png

可以通过类查看类的实例和引用类型,追踪到垃圾回收的根节点,只要能够访问到根节点就是可达,有可达线路的对象就不会被回收

总结

对于这两个可视化监控工具来说更多的是在测试环境调试问题的时候会用到,因为像这样的监控信息在生产环境中不仅仅只有一台可能是多台

那么对于生产环境而言这两个可视化工具就没有太大的用武之地了,生产环境中使用更多的是将每个实例的jvm信息收集起来形成统一监控报表

但是对于命令工具还是有必要去了解的,当生产环境中某台服务器出现CPU100%、内存泄露、死锁被监控工具检测出来以后就需要到对应的服务器上排查

当然业界也有很多优秀的线上监控诊断产品,比较典型的就是Arthas它可以通过全局视角实时查看应用load、内存、gc、线程的状态信息