jdk在安装的时候会提供一些性能分析、故障诊断、JVM监控之类的工具,了解这些工具对我们分析JVM内存、JVM调优有一定的帮助,本篇文章来学习一下。
监控类工具
jps
jps(JVM Process Status)是查看正在运行的虚拟机进程的工具。jps能获取进程id,所以会被经常使用。在 linux 中,一般自带了 OpenJdk,一般情况下 JPS 等命令不能用,要么选择去安装 JPS 等插件,要么把 OpenJdk 卸载,重新安装 Oracle 的 JDK。
语法:jps [ options ] [ hostid ]
- options可选项,有以下选择:
参数 | 含义 |
-q | 只显示进程 |
-m | 输出主函数传入的参数 |
-l | 输出应用程序主类完整 package 名称或 jar 完整名称. |
-v | 列出 jvm 参数 |
-V | 只生成本地JVM标识符列表 |
-J | 向JVM传递参数。例如:-J-Xms48m,设置JVM初始内存为48m |
- hostid :远程地址,可选项,指定特定主机的IP或者域名,也可以指定具体协议端口,不指定则查看当前机器的相关信息,hostid所指机器必须开启jstatd服务。
测试:
57312 JvmToolsApplication
这个是我运行的一个用于测试的springboot项目。
jstat
jstat(JVM Statistics Monitoring Tool )是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据,在没有 GUI 图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
语法: jstat [ generalOption | outputOptions vmid [ interval[s|ms] [ count ] ]
- generalOption :常规选项,必填项。有两个参数可选
-
-help
:帮助信息 -
-options
:对应着下面的outputOptions
- outputOptions:输出选项,必填项。有以下选项
参数 | 含义 |
-class | 显示类加载器行为信息 |
-compiler | 显示有关JVM实时编译器行为的统计信息 |
-gc | 显示有关GC堆行为的统计信息。 |
-gccapacity | 显示各分区大小 |
-gccause | 显示最近一次 GC 统计信息和原因 |
-gcnew | 显示新生代行为的统计信息。 |
-gcnewcapacity | 显示新生代内存大小 |
-gcold | 显示老年代统计信息 |
-gcoldcapacity | 显示老年代内存大小 |
-gcmetacapacity | 显示元空间内存大小 |
-gcutil | 显示GC统计汇总信息 |
-printcompilation | 显示HotSpot 编译统计信息 |
outputOptions参数后面还能加以下可选参数:
- -h n:每n个样本(输出行)显示一个列标题,默认值为0,显示列标题的第一行数据。
- -t:第一列显示为时间戳
- -J:向应用程序传递启动参数
- vmid :虚拟机标识
- interval:指定时间采样间隔时间,单位秒(s)或者毫秒(ms),默认单位是毫秒
- count :采样次数,指定时间内采样多少次。
测试:
- 统计gc信息
- 57312 是测试项目JvmToolsApplication在虚拟机中的进程id。
-
jstat -gc 57312 100 10
这个命令是在100ms内获取10次gc统计信息 - 结果中的列分别代表以下意思:
- S0C:第一个幸存区(From 区)的大小
- S1C:第二个幸存区(To 区)的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:伊甸园(Eden)区的大小
- EU:伊甸园(Eden)区的使用大小
- OC:老年代大小
- OU:老年代使用大小
- MC:方法区大小
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
故障诊断类工具
jinfo
jinfo(Configuration Info for Java) 可以实时地查看和调整虚拟机的各项参数。jinfo不仅能获取到虚拟机命令行参数,还能获取到系统参数。
语法:
-
jinfo [ option ] pid
:查看和调整本地进程虚拟机参数
option:
- -flag name:name为jvm参数名
- -flag [+|-]name:开启或者关闭一个Boolean的jvm参数
- -flag name=value:设置jvm参数值
- -flags:查询虚拟机参数
- -sysprops:可以查看由 System.getProperties()取得的参数
测试:
- flag测试
可以通过java -XX:+PrintFlagsFinal –version
命令获取虚拟机参数,这是一个很长的列表,其中红框部分如果是manageable则表示可以在运行时修改。 - 我们就随便找一个参数UseTLAB进行查询,可以看到它是否开启
- 获取虚拟机参数
先修改一下项目启动参数,加上-XX:+PrintGC -XX:SurvivorRatio=6
: - 重启项目,并通过jps获取到进程id
- 再通过
jinfo -flags 67776
命令获取项目启动参数 - 还可以获取上面配置的某一个参数
jinfo -flag SurvivorRatio 67776
通过 jinfo 命令,我们可以在生产上临时打开一下 GC日志或者进行一些数据的配置(不需要重启应用条件下),也是我们去排查问题的一个关键命令。
jmap
jmap(Memory Map for Java) 打印给定进程或远程调试服务器的共享对象内存映射或堆内存详细信息。jmap也可用于生成堆转储快照(一般称为 heapdump 或 dump 文件),除此之外它还可以查询 finalize 执行队列、Java 堆和永 久代的详细信息,如空间使用率、当前用的是哪种收集器等。和 jinfo 命令一样,jmap 有不少功能在 Windows 平台下都是受限的,除了生成 dump 文件的 -dump 选项和用于查看每个类的实例、空间占用统计的-histo 选项在所有操作系统都提供之外,其余选项都只能在 Linux/Solaris 下使用。
语法:jmap [ options ] pid
options 有如下选项:
- -heap:打印 heap 的概要信息
Heap Configuration: ##堆配置情况,也就是 JVM 参数配置的结果[平常说的 tomcat 配置 JVM 参数,就是在配置这些]
MinHeapFreeRatio = 0 //最小堆使用比例
MaxHeapFreeRatio = 100 //最大堆可用比例
MaxHeapSize = 4261412864 (4064.0MB) //最大堆空间大小
NewSize = 88604672 (84.5MB) ) //新生代分配大小
MaxNewSize = 1420296192 (1354.5MB) //最大可新生代分配大小
OldSize = 177733632 (169.5MB) //老年代大小
NewRatio = 2 //新生代比例
SurvivorRatio = 6 //新生代与 suvivor 的比例
MetaspaceSize = 21807104 (20.796875MB) //元空间大小
CompressedClassSpaceSize = 1073741824 (1024.0MB) //类指针压缩空间大小
MaxMetaspaceSize = 17592186044415 MB // 最大元空间大小
G1HeapRegionSize = 0 (0.0MB) //G1收集器Region单元大小
Heap Usage: //堆内存实际的使用情况
PS Young Generation //新生代
Eden Space: //Eden 区
capacity = 66584576 (63.5MB) //Eden容量
used = 27941200 (26.646804809570312MB) //Eden区已使用大小
free = 38643376 (36.85319519042969MB) //未使用
41.96347214105561% used //使用比例
From Space: //survior1 区
capacity = 11010048 (10.5MB)
used = 8497840 (8.104171752929688MB)
free = 2512208 (2.3958282470703125MB)
77.18258812313988% used
To Space: //survior2 区
capacity = 11010048 (10.5MB)
used = 0 (0.0MB)
free = 11010048 (10.5MB)
0.0% used
PS Old Generation //老年代使用情况
capacity = 115867648 (110.5MB)
used = 10553152 (10.06427001953125MB)
free = 105314496 (100.43572998046875MB)
9.10793666925905%
- -histo 打印每个 class 的实例数目,内存占用,类全名信息.
语法:jmap –histo:live <pid>
,live参数表示统计活跃状态的对象 - -histo 打印的实例数目太多了,看不过来,显示那么多也没什么用,所以在Linux系统上可以使用
jmap –histo <pid> | head -10
命令只展示前10行,具体行数可以自己定义。 - -finalizerinfo :打印正等候回收的对象的信息
- –clstats:打印堆中类加载器信息,它会打印类加载器的名字、活跃度、地址、父加载器、加载了多少个类等。
- -dump:[live,] format=b, file=filename:生成的堆转储快照
- 通过-dump命令可以在指定文件夹生成dump文件,之后再搭配jhat来分析dump文件,dump文件的后缀也可以是
hprof
或者bin
,dump文件本身是一个二进制文件。 - -h或-help:打印帮助信息
- -J:传递虚拟机参数
jhat
jhat (Heap Dump Browser)可以让一个dump文件以web服务的的形式访问。
上面我们用jmap工具生成了一个dump文件,现在可以通过jhat 工具,让它再浏览器端访问到。
Server is ready表示启动成功,端口号为7000,然后在浏览器端访问http://localhost:7000/,可以看到dump文件内容
语法:jhat [ options ] heap-dump-file
- -stack false|true:关闭对象分配调用栈跟踪。 如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true.
- -refs false|true:关闭对象引用跟踪。 默认值为 true. 默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用, 会统计/计算堆中的所有对象。
- -port port-number:http端口号指定,就是上面通过浏览器访问的端口号,默认是7000
- -exclude exclude-file:指定一个文件,该文件列出应从可达对象查询中排除的数据成员。
- -baseline exclude-file:指定基线堆转储。两个堆转储中具有相同对象ID的对象被标记为不是新的。其他对象被标记为新的。这对于比较两个不同的堆转储非常有用。
- -debug int:设置debug等级,0意味着不输出debug信息,等级越高输出的日志越详细。
- -version:版本号
jhat命令在JDK9、JDK10中已经被删除了,官方建议使用VisualVM代替。
jstack
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主 要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。
语法:jstack [ options ] pid
options 选项:
- -m:打印同时具有Java和本机C/C++帧的混合模式堆跟踪。
- -l:打印有关锁的其他信息,例如拥有java.util.concurrent同步器的列表
可视化工具
对于桌面操作系统,java提供了jconsole和jvisualvm可视化工具。可视化工具就是将上面几个命令行工具整合到一起使用的一个工具。
jconsole
jconsole命令启动一个图形控制台工具,该工具允许您监视和管理本地或远程计算机上的Java应用程序和虚拟机。
命令行输入Jconsole
命令
选择要监控的程序,可选择本地进程也可以选择远程进程,如果选择远程进程的话要在服务器开启JMX,一般不开启。
进入控制台首页
- 概览:可以看到堆内存的使用量、线程、类加载的变化、CPU占用率
- 内存:可以看到各个分区的使用量变化,也可以执行GC操作
- 线程:可以看到线程数变化情况,也可以查看具体线程详细信息,检测是否有死锁
- 类:类加载数量变化的折线图,可根据时间范围进行筛选
- VM概要:查看JVM各种信息的汇总
- MBean:查看Mbean信息、属性信息、方法信息等。通过getProperty可以获取系统属性,比如在输入框输入
sun.desktop
,就会弹出对应的属性值。 - JConsole启动的时候还可以附加其他参数:
- -interval=n:更新间隔频率,单位秒(s),默认4秒更新一次
- -notile:对于2个及以上连接不平铺窗口
- -pluginpath plugins:启动的同时指定一个插件
jvisualvm
jvisualvm是一个监控运行时java应用程序的图形界面工具。jvisualvm大致和Jconsole差不多,就是多了抽样器和profiler,感兴趣的可以自己试一下。
命令行输入jvisualvm
就可以启动jvisualvm可视化界面了。
选择要查看的应用程序就可以进入监控界面
jhat命令是用来加载jmap生成的dump文件的,前面不是说官方建议使用VisualVM代替jhat命令嘛,那就是说jvisualvm也可以加载dump文件。
选择堆dump
打开就能看到之前生成的dump文件里面的内容了
jvisualvm还可以安装插件
这里选择安装Visual GC
安装好之后就可以看到jvm内存变化情况,通过Visual GC可以很好地理解JVM运行时区域信息。
总结
以上就是关于JVM的一些优化工具,这里只是简单的介绍了一下,有兴趣的可以深入了解一下,对JVM进行优化时大有用处。