当前位置:网站首页 > 技术博客 > 正文

java编写命令行工具



 

 

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 做两个用途

  1.  通过查看 jstat 打印的数据,调整JVM配置参数
  2. 查看代码中是否存在内存泄漏
  3. 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 无法获取:

  1. 当多个GC事件发生时,无法获取某单个GC的pause时间
  2. 无法获取sys和user的执行时间
  3. 每次GC事件后,有多少内存被回收掉

因此实际分析问题时,还需要结合其它工具一起分析JVM的性能,其它工具后续会持续介绍。

 

 

版权声明


相关文章:

  • linux inet_ntoa函数2025-05-05 07:01:05
  • plantuml vim2025-05-05 07:01:05
  • 背包问题动态规划表2025-05-05 07:01:05
  • 分区mbr格式是什么意思2025-05-05 07:01:05
  • 霍夫变换应用规则2025-05-05 07:01:05
  • 进程线程的概念和区别2025-05-05 07:01:05
  • 潘多拉固件怎么桥接wifi2025-05-05 07:01:05
  • 计算机操作系统组成部分有哪些2025-05-05 07:01:05
  • 字符串数组怎么定义,java2025-05-05 07:01:05
  • vue3使用vue2组件2025-05-05 07:01:05