深入理解Java虚拟机读书笔记(3): JDK自带工具详解汇总(不断更新)
对于初学者来说,学习Java时可能仅仅认识了java
和javac
两个命令,其他的命令没有基础过。其实jdk自带了非常多的非常好用的工具,在windows环境下,打开jdk下的bin目录,可以看到很多exe文件,如下图所示:
同样的,在linux环境下jdk的bin目录下也一样提供了很多工具,这些是编译好的二进制可执行脚本:
下面就比较常用的一些工具做具体介绍。
做介绍之前,提供一个官方的文档,所有命令的用法介绍、参数详解、结果详解都可以查询到
地址为:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html
此为JDK1.8的,其他版本自己对应查找连接即可。
下面介绍的时候也是按照官方文档的分类方法。
监控JVM的命令
一、jps
对于搞大数据的人来说,jps命令可以说是最常用的命令之一了,它可以用来查看当前运行的虚拟机进程。官方文档地址
使用方法为jps [option] [hostid]
参数介绍:
-q 仅输出VM标识符,不包括class name,jar name,arguments in main method,也就是仅输出进程ID了
-m 输出main method的参数
-l 输出完全的包名,应用主类名,jar的完全路径名
-v 输出jvm参数
-V 输出通过flag文件传递到JVM中的参数.hotspotrc文件或-XX:Flags=所指定的文件
-Joption 传递参数到vm,例如:-J-Xms48m
hostid一般是本地java进行id,也可以是远程的,格式如下
[protocol:][[//]hostname][:port][/servername]
如果需要查看其他机器上的jvm进程,需要在待查看机器上启动jstatd。
命令的输出格式 :
lvmid [ [ classname| JARfilename | “Unknown”][ arg* ] [ jvmarg* ] ]
几种使用情况介绍:
1) 无任何参数,直接jps,此时默认输出所有jvm进程,并打印ID和主类名
2) jps -q 仅显示进程id
3) jps -l 输出完全的包名,主类名,jar完全路径名
4) jps -v 显示jvm参数
jps用法简单,使用频率非常高。
二、jstat
这个命令用于分析某个jvm进程的jvm的使用情况的统计信息,命令格式为:
jstat [ generalOption | outputOptions vmid [ interval[s|ms] [ count ] ]
具体介绍:
generalOption:其实就是-h或者-options
outputOptions:由单个statOption或加上其他-t、-h和-J组成的options,用于确定输出的内容和格式
输出是表格的形式,表头字段用于描述列内容。-h设置表头的打印频率,例如-h3用于表示每3行打印一次表头部。使用-t选项显示时间戳列,标记为Timestamp作为输出的第一列。Timestamp列包含自目标JVM启动以来经过的时间(以秒为单位)。时间戳的分辨率取决于各种因素,并且由于在高负载系统上延迟的线程调度而受到变化。
vmid: Virtual machine identifier的缩写,一般就是本地进程ID或者是远程服务器进程
interval[s|ms]: 秒或者毫秒,即多少秒/毫秒打印一次,默认为毫秒
count: 一共打印多少次
官方不建议编写脚本来解析jstat命令的输出,因为格式会在不同版本中更改。
一些-statOption:
参数名称 | 参数作用 |
---|---|
class | 显示有关类加载方面的统计信息 |
compiler | 显示有关Java HotSpot VM实时编译器行为的统计信息 |
gc | 显示有关垃圾回收堆行为的统计信息 |
gccapacity | 显示有关代的容量及其相应空间的统计信息 |
gccause | 显示有关垃圾收集统计信息(与-gcutil相同)的摘要,其中包含最后一个和当前垃圾收集事件的原因 |
gcnew | 显示年轻代行为的统计信息 |
gcnewcapacity | 显示有关年轻代及其相应空间大小的统计信息 |
gcold | 显示有关老年代和元数据空间统计信息行为的统计信息 |
gcoldcapacity | 显示有关老年代大小的统计信息 |
gcmetacapacity | 显示有关元数据空间大小的统计信息 |
gcutil | 显示有关垃圾收集统计信息的摘要 |
printcompilation | 显示Java HotSpot VM编译方法统计信息 |
举例如下:
如下表示分析进程id为31736 的gc情况,每隔1000ms打印一次记录,打印10次停止,每3行后打印指标头部
jstat -gc -h3 11919 1000 10
结果如下所示:
结果指标含义如下:
参数 | 描述 |
---|---|
S0C | 年轻代中第一个survivor(幸存区)的容量 (字节) |
S1C | 年轻代中第二个survivor(幸存区)的容量 (字节) |
S0U | 年轻代中第一个survivor(幸存区)目前已使用空间 (字节) |
S1U | 年轻代中第二个survivor(幸存区)目前已使用空间 (字节) |
EC | 年轻代中Eden(伊甸园)的容量 (字节) |
EU | 年轻代中Eden(伊甸园)目前已使用空间 (字节) |
OC | 老年代的容量 (字节) |
OU | 老年代目前已使用空间 (字节) |
PC | Perm(持久代)的容量 (字节) |
PU | Perm(持久代)目前已使用空间 (字节) |
YGC | 从应用程序启动到采样时年轻代中gc次数 |
YGCT | 从应用程序启动到采样时年轻代中gc所用时间(s) |
FGC | 从应用程序启动到采样时老年代(全gc)gc次数 |
FGCT | 从应用程序启动到采样时老年代(全gc)gc所用时间(s) |
GCT | 从应用程序启动到采样时gc用的总时间(s) |
其他命令统计结果可以查阅文档, 一般都是生产环境下不方面使用其他工具的时候使用此命令大致查看gc信息。
三、jstatd
这是一个远程调用服务程序,监视Java虚拟机(JVM)并使远程监视工具能够连接到JVM。比如jps、jinfo等对远程服务器使用,那么远程服务器上就要启动jstatd才可以。
用法:
jstatd [options]
参数命令:
-nr : 当找不到现有的RMI注册表时,不会尝试在jstatd进程中创建内部RMI注册表。
-p port : 如果未指定-nr选项,则在创建RMI注册表或未找到RMI注册表时创建的端口号。
-n rminame: 远程RMI对象在RMI注册表中绑定到的名称,默认名称为JStatRemoteHost。如果一个服务器上启动了多个jstatd服务,可以使用此参数为不同的jstatd服务指定唯一标识。
-Joption: 传递JVM的参数,其中option是Java应用程序启动器参数。例如,-J-Xms48m将启动内存设置为48 MB
故障排除命令
二、jinfo
jinfo 是jdk自带的一个工具,它可以用来查看正在运行的java应用程序的扩展参数
(JVM中-X、-XX标示的参数),甚至支持在运行时修改部分参数。配置信息包括Java系统属性和Java虚拟机(JVM)命令行参数。对于64位JVM,可以加一个可选参数 -J-d64
,例如jinfo
-J-d64 -sysprops pid
.
用法如下:
jinfo [option] <pid>
用于连接正在运行的进程
jinfo [option] <executable <core>
用于连接一个核文件
jinfo [option][server_id@]<remote server IP or hostname>
用于连接一个远程debug服务器
option参数如下:
-flag 打印指定的name参数的名称和值
-flag [+|-] 使用或取消名称为name的Boolean参数
-flag = 设置name参数为给定value
-flags 打印所有传递给JVM的命令行参数
-sysprops 打印Java系统属性
打印上面所有内容
-h | -help 打印帮助信息
1) jinfo -flags pid
2) jinfo -flag -XX:CICompilerCount pid 查看某个具体的参数的值
二、jmap
jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件) ,此文件是分析应用程序可能发生的问题以及调优的重要文件。jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、 Java堆和永久代的详细信息,如空间使用率、 当前用的是哪种收集器等 。
命令格式:
jmap [ options ] pid
option可选值介绍如下:
参数 | 含义 |
---|---|
-dump | 生成java堆转储快照。格式为:-dump:[live,] format=b, file=filename,live参数作用是控制是否只dump出存活的对象,存储文件为hporf二进制文件。可以配合jhap命令浏览分析转储出的文件。 |
-finalizerinfo | 显示在F-Queue中等待Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效。 |
-heap | 显示Java堆中的详细信息,包括使用哪种收集器、参数配置、分代状况等,只在Linux/Solaris平台下有效。 |
-histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat | 以ClassLoader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效。 |
-F | 当虚拟机进程堆-dum参数没有响应时,可以使用这个选项强制生成dump快照。只在Linux/Solaris平台下有效。 |
-clstats | 显示Java堆的类加载器的统计信息。对于每个类加载器,它的名称,活动程度,地址,父类加载器以及它加载的类的数量和大小都会被打印出来。 |
三、jhat
jhat(Java Heap Analysis Tool)一般与jmap搭配使用,用途分析jmap生成的堆转储快照。jhap内置一个http服务器,可以在浏览器中查看分析结果。但是这个工具分析结果比较简陋,而且一般不会直接在服务器上直接分析dump文件,所以比较鸡肋。有很多其他优秀的分析工具可以使用,比如VisualVM、MAT等,后面会介绍。
命令格式:
jhat filename
可视化监控与分析Java应用程序
一、JConsole
jconsole命令启动图形控制台工具,可以监视和管理本地或远程计算机上的Java应用程序和虚拟机。它基于JMX技术,它管理部分的功能是针对JMX MBean进行管理,MBean可以使用代码、 中间件服务器的管理控制台或者所有符合JMX规范的软件进行访问。
在Windows下,启动在jdk/bin 下的jconsole.exe以后将自动搜索出本机运行的所有虚拟机进程,不需要通过jps来查询,然后选择一个进程即可开始监控。如下图所示:
jconsole包含了非常丰富的信息,主界面如下图所示:
可以看到,可以查看概述、内存、线程、类、vm概要、MBean等六大类信息,每一类下面都包括丰富的图标和文字统计信息,非常强大。
“概述”页签显示的是整个虚拟机主要运行数据的概览,其中包括“堆内存使用情况”、“线程”、 “类”、 “CPU使用情况”4种信息的曲线图。
“内存”页签相当于可视化的jstat命令
,用于监视受收集器管理的虚拟机内存(Java堆和永久代)的变化趋势。
“线程”页签的功能相当于可视化的jstack命令,遇到线程停顿时可以使用这个页签进行监控分析。
“VM概要”里面则显示了虚拟机的信息,如下图所示:
二、 VisualVM
VisualVM(All-in-One Java Troubleshooting Tool) 是到目前为止随JDK发布的功能最强大的运行监视
和故障处理
程序 ,它不仅可以用来运行监视、故障处理,还可以用来进行性能分析
。
它还支持插件拓展
。结合插件,VisualVM可以做到很多强大的功能,比如:
- 显示虚拟机进程以及进程的配置、 环境信息(jps、 jinfo)
- 监视应用程序的CPU、 GC、 堆、 方法区以及线程的信息(jstat、 jstack)
- dump以及分析堆转储快照(jmap、 jhat)
- 方法级的程序运行性能分析,找出被调用最多、 运行时间最长的方法
- 离线程序快照:收集程序的运行时配置、 线程dump、 内存dump等信息建立一个快照,可以将快照发送开发者处进行Bug反馈
- …
其程序主界面如下图所示:
选择本地某个进程点进去,发现其主要功能和JConsole差不多,但是其支持插件,所以有更多强大的功能,而且可视化界面更加友好。在监视选项卡下支持堆dump,点击之后会生成堆dump文件,并自动加载分析,得到分析结果,如下所示:
当VisualVM关闭时,此dump文件会自动删除,所以如果想要保存,需要在选项卡上右击另存为。
VisualVM还支持分析程序性能的功能。在Profiler页签中,VisualVM提供了程序运行期间方法级的CPU执行时间分析以及内存分析,做Profiling分析肯定会对程序运行性能有比较大的影响,所以一般不在生产环境中使用这项功能。 选择“CPU”和“内存”按钮中的一个,然后切换到应用程序中对程序进行操作,VisualVM会记录到这段时间中应用程序执行过的方法。 比如如果是CPU分析,将会统计每个方法的执行次数、 执行耗时;如果是内存分析,则会统计每个方法关联的对象数以及这些对象所占的空间。
VisualVM有两个很重要的插件,VisualGC
和BTrace动态日志跟踪
。
VisualGC对进程的GC情况作了统计和可视化,效果如下所示:
BTrace的作用是在不停止目标程序运行的前提下,通过HotSpot虚拟机的HotSwap技术[4]动态加入原本并不存在的调试代码。 这项功能对实际生产中的程序很有意义:经常遇到程序出现问题,但排查错误的一些必要信息,譬如方法参数、 返回值等,在开发时并没有打印到日志之中,以至于不得不停掉服务,通过调试增量来加入日志代码以解决问题。 当遇到生产环境服务无法随便停止时,缺一两句日志导致排错进行不下去是一件非常郁闷的事情。
BTrace脚本编写和Java很像,但也有很多东西需要学,这里暂时不多做介绍。
至于插件的安装,非常简单,在菜单栏的工具->插件点击即可,如下图所示:
选择想要安装的插件点击安装即可自动下载安装,也可以去VisualVM官网去下载插件然后放到指定的位置,这里不多做介绍,有兴趣的可以自己查阅资料。[插件官方地址](