
jstat 是JDK中提供的一个命令行工具,主要用来打印JVM 性能数据相关的统计数据。主要包含以下几个方面:
- 垃圾回收(GC)方面数据
- 编译(Compilation)相关数据
- 类加载信息(Class Loader)
jstat 最大的优势就是可以在JVM运行时,实时的抓取这些数据。
如何启动 jstat
jstat 使用很简单,只要在命令行中执行如下命令:
jstat -gc -t 11256 10000 10
参数解释:
- -gc :打印相关的统计参数
- -t: 在每行日志之前加上JVM的启动时间
- 11256 : 目标Java进程的ID
- 10000: jstat命令执行间隔时间(milliseconds),10000表示每10s打印一行日志
- 10: jstat命令的执行次数,(和上面的时间间隔一起,表示jstat会每10s执行1次,总共执行10次).
执行结果:
上面命令行执行后的结果类似于以下格式:
jstat 打印的信息很多且杂,要了解其中各部分代表的意义需要先对JVM中堆内存有一定的了解。在JVM中,堆内存分为年轻代和老年代;年轻代因为使用复制回收算法,也被分为、 和 ,如下图所示:

了解了堆内存的分布,再看jstat的打印参数就很容易理解了。
参数意义:
- time : JVM启动时间(单位为秒)
- S0C :年轻代中S0区的容量 (字节)
- S1C :年轻代中S1区的容量 (字节)
- S0U :年轻代中S0区目前已使用空间 (字节)
- S1U :年轻代中S1区目前已使用空间 (字节)
- EC :年轻代中Eden区的容量 (字节)
- EU :年轻代中Eden区目前已使用空间 (字节)
- OC :老年代的容量 (字节)
- OU :老年代目前已使用空间 (字节)
- YGC :从应用程序启动到采样时年轻代中GC次数
- YGCT :从应用程序启动到采样时年轻代中GC所用时间(s)
- FGC :从应用程序启动到采样时老年代(全GC)GC次数
- FGCT :从应用程序启动到采样时老年代(全GC)GC所用时间(s)
- GCT:从应用程序启动到采样时GC用的总时间(s)
解析执行结果
通过上面的jstat打印日志,基本可以得出如下结论:
注意:其实除了 -gc 之外,jstat 还有很多其它子命令
实战演练
我一般使用 jstat 做两个用途
- 通过查看 jstat 打印的数据,调整JVM配置参数
- 查看代码中是否存在内存泄漏
- 1. 调整JVM配置参数
如下代码 JstatDemo.java:
上述代码分别使用两个线程 PigEater 和 PigEater 来代表线程执行的吞吐量。
接下来通过配置不同JVM配置,分别执行上述代码,并查看代码执行效果。
配置1:
- 设置堆内存大小为4G (-Xms4g –Xmx4g)
- 使用CMS回收器回收老年代(-XX:+UseConcMarkSweepGC),使用Parallel回收算法回收年轻代(-XX:+UseParNewGC)
- 设置年轻代Eden区大小为512M(-Xmn512m)
配置2:
- 设置堆内存大小为2G(-Xms2g –Xmx2g)
- 使用Parallel回收器回收年轻代和老年代垃圾对象 (-XX:+UseParallelGC)
- 设置年轻代Eden区为1536M(-Xmn1536m)
分别通过如下两个命令执行配置1和配置2代码,在执行过程中同时执行 jstat 命令

执行结果为:

可以看出配置2的执行时间更短,执行效率更高。可是配置1的分配内存是配置2的2倍,按照正常思维应该更快一些,而结果却是相反。这是为什么呢?如果要分析原因,可以借助于 jstat 工具来分析。
配置1执行 jstat 结果如下:
配置2执行 jstat 结果如下:
仔细看可以看出配置1经历了1129次GC事件(YGC + FGC),用时63.723秒(YGCT + FGCT)。而配置2只是经历了168次GC回收,用时11.409秒。大量的GC会造成程序性能降低。
结论:
虽然配置2比配置1的内存小1倍,但是吞吐量却比配置1更高。因此JVM参数的配置还是要根据实际项目、实际情况。
2. 查看代码是否存在内存泄漏
在长时间运行的Java程序中,可以通过运行 jstat 命令连续获取多行GC相关数据,并取这几行数据中的OU(也就是老年代已用容量)的值。
然后,每隔一段较长时间重复一次上述操作,来获取多组OU值。如果这些值呈上升趋势,则说明该Java程序的老年代内存已使用量不断上涨,因此无法被回收的对象在不断增长,很有可能存在内存泄漏。
jstat 缺陷
很明显 jstat 也不是万能的,最大缺陷就是GC日志不详细。
主要有以下几个方面的信息 jstat 无法获取:
- 当多个GC事件发生时,无法获取某单个GC的pause时间
- 无法获取sys和user的执行时间
- 每次GC事件后,有多少内存被回收掉
因此实际分析问题时,还需要结合其它工具一起分析JVM的性能,其它工具后续会持续介绍。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/9247.html