Java之jstat的用法:Java虚拟机 统计信息查看 工具 - Go语言中文社区

Java之jstat的用法:Java虚拟机 统计信息查看 工具


全称“Java Virtual Machine statistics monitoring tool”(statistics 统计;monitoring 监控;tool 工具)

用于监控虚拟机的各种运行状态信息的命令行工具。

可以查看虚拟机中进程的类加载,内存,垃圾回收、jit编译等运行数据。

jstat 命令格式: jstat [-option] [vmid] [int   s|ms] [count] 

例如: jstat -class 64363  1s 10

简单解释: -class 是option的选项参数,要看类加载信息;64363是es的pid 1s 就是间隔一秒执行一次,10 就是执行10次

后面的执行时间和执行次数可以不写,那就默认执行一次。

可以看下面的-class选项的说明中的这个命令的执行效果图。

                                           《深入理解Java虚拟机》上面弄的截图。

一眼望去,关于gc的选项很多,也说明实际现场出问题差不多都跟gc的STW时间太久导致程序间歇性死亡假死或者直接gg。比如es要是gc时间久了,就完蛋了。

 

下面分别看看,顺便亲自手动试试每个option命令(在jdk 1.8 的环境下测试的截图)

1, -class 监视类装载、卸载数量,总空间、类装载所耗费时间

具体例子:jstat -class 64363  1s 10

  • Loaded:加载class的数量  Number of classes loaded.
  • Bytes: Number of kBs loaded.
  • Unloaded:卸载class数量(这个unloaded 翻译成未加载呢?我觉得不合适吧)
  • Bytes: Number of Kbytes unloaded.
  • Time:Time spent performing class loading and unloading operations. 执行 类加载和卸载操作所花费的时间

查看es进程的类加载信息,es的pid是64363 ,间隔1s执行一次,一共执行10次。

elasticsearch的运行要加载一万两千多个类呢,还有unloaded 类。

这不是未加载的意思。

 

2,-compiler 输出jit编译器编译过的方法耗时等信息

jstat -compiler 64363

  • Compiled:执行的编译任务数量。Number of compilation tasks performed.
  • Failed:失败数量
  • Invalid:不可用数量
  • Time:时间
  • FailedType:失败类型
  • FailedMethod:失败的方法

还是使用es的进程来搞实验,编译的数量是2万多,但是load的class数量才一万多,为什么?

我这么解释:把整个项目都给编译一遍,但是并不是所有的类都会被jvm加载。这么解释还凑合吧。

 

3,-printcompilation  输出已经被jit编译的方法

jstat -printcompilation 629756

额,我也不知道这个jit是干啥的,就摆个截图放这吧,这个不是es而是另一个消费kafka的进程的pid。

 

4,-gc  监视Java堆状况,eden,2个s区,old,元空间等容量,gc时间等情况

jstat -gc 64363 1s 100 

看es进程的gc情况,一秒一刷执行100次,执行一次,遇不到gc 

以下几个容量大小的单位都是 kb,包括后面的几个option的截图,里面容量的单位都是 kb

  • S0C:第一个幸存区的大小(S0 Capacity)
  • S1C:第二个幸存区的大小(S1 Capacity)
  • S0U:第一个幸存区的使用大小(S0 Used / utilization   还是used单词简单)
  • S1U:第二个幸存区的使用大小(S1 Used)
  • EC:伊甸园区的大小(Eden Capacity  伊甸园 亚当夏娃造人的公园,不造的科普一下。)
  • EU:伊甸园区的使用大小(Eden Used)
  • OC:老年代大小(Old Capacity)
  • OU:老年代使用大小(Old Used)
  • MC:元空间大小(Metaspace Capacity 已经不是之前叫的method area了,现在改名叫元空间了,虽然都是M开头的)
  • MU:元空间使用大小(Metaspace Used)
  • CCSC:压缩类空间大小 (Compressed class space capacity (kB).)
  • CCSU:压缩类空间使用大小(Compressed class space used (kB).)
  • YGC:年轻代垃圾回收次数(young gc)
  • YGCT:年轻代垃圾回收消耗时间(young gc time)
  • FGC:对堆内存整体包含新生代,老年代,永久代)进行垃圾回收次数(full gc)
  • FGCT:对堆内存整体包含新生代,老年代,永久代)进行垃圾回收消耗时间(full gc time)
  • GCT:垃圾回收消耗总时间(gc time)

一直在看的elasticsearch的进程的一些参数设置的截图,使用的命令:jps -vm |grep elastic

从上面的gc的图,可以看出不少理论:

1,2个s区,但是一直有个s区的used是0.0,是空白的。

2,2个s区大小是一致的

3,上面截图中出现一次young gc(0.0换列的那个地方),YGC 次数由10703次变成10704次,加1,young gc之前,eden区都快满了538926.4 / 545344 = 98.8%了,gc之后,s1被完全回收,eden区的空间被回收大部分,s0区被安排了些新生的数据对象,old used 由529563.2变成了529706.2,增加了一点点,说明有部分对象被安排到了老年代去了。后面的gc time肯定不是某一次的gc时间,而是从启动到现在的总时间,从图中看到没有发生gc之前,这个值是一直不变的,gc之后,稍微长大了一丢丢。算一下,一次young gc的时间是0.011秒,full gc 没有在打印期间触发,后面的整个gc 时间增加也就0.01秒。启动2天的es的full gc的次数136,整个full gc的时间也就8秒多。启动之后整个程序的所有gc时间400多秒。

4,young gc 的次数比full gc的次数少的多,一个是1.1万次,一个是100多次。

(full难道不是整个堆内存吗?为啥有的人说full gc是对old区进行gc呢?我反对。所以,我上面写的就是对整个堆内存gc)

 

5,-gccapacity  与-gc基本相同,主要关注Java堆各区域使用到的最大最小空间

jstat -gccapacity 64363 1s 100

  • NGCMN:新生代最小容量 (New  Generation Capacity Min)
  • NGCMX:新生代最大容量(New  Generation Capacity Max)
  • NGC:当前新生代容量(New  Generation Capacity)
  • S0C:第一个幸存区大小(S0 Capacity)
  • S1C:第二个幸存区的大小(S1 Capacity)
  • EC:伊甸园区的大小(Eden Capacity  伊甸园 亚当夏娃造人的公园,不造的科普一下。)
  • OGCMN:老年代最小容量(Old  Generation Capacity Min)
  • OGCMX:老年代最大容量(Old  Generation Capacity Min)
  • OGC:当前老年代大小(Old Generation Capacity)
  • OC:当前老年代大小(Old Capacity)
  • MCMN:最小元数据容量(Metasapce Capacity Min)
  • MCMX:最大元数据容量(Metasapce Capacity Max)
  • MC:当前元数据空间大小(Metasapce Capacity)
  • CCSMN:最小压缩类空间大小
  • CCSMX:最大压缩类空间大小
  • CCSC:当前压缩类空间大小
  • YGC:年轻代gc次数(young gc)
  • FGC:对堆内存整体包含新生代,老年代,永久代)GC次数 (full gc)

Java内存的差不多每个分区都有相应的配置来设置这个区域的最大值和最小值,在实际分配空间的时候,不够的时候会自动扩展,直到达到此区域的最大值,还无法满足程序在内存分配空间的时候,才会报OOM异常。想一下jvm里面几个分区的OOM情况。

在上面的实际图中,年轻代,老年代的最大最小设置的一样的,所以这2个分区的大小就是固定的,另外2个元空间和压缩类空间最小值是0,那大小会动态变化的就是后面这2个分区,以及young gc和full gc的次数了。截图中并没有发生young gc。

 

6,-gcutil   与-gc基本,主要关注已使用空间占此空间的百分比

jstat -gcutil 64363 1s 100

  • S0:幸存1区当前使用比例
  • S1:幸存2区当前使用比例
  • E:伊甸园区使用比例
  • O:老年代使用比例
  • M:元数据区使用比例
  • CCS:压缩使用比例
  • YGC:年轻代垃圾回收次数
  • YGCT:年轻代垃圾回的总时间
  • FGC:对堆内存整体包含新生代,老年代,永久代)垃圾回收次数
  • FGCT:对堆内存整体包含新生代,老年代,永久代)垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

截图里面发生了一次young gc,2个s区一个被清空,eden区的使用率99.75变成9.6之后,一路往上涨,最终又触发下一次young gc

old区百分比比较稳定,说明堆里面的对象基本都在这个eden区出生,在新生代中,大部分对象都干完事儿就被和谐了,内存使用正常,要是代码中有会造成内存溢出的代码,那么这个old区的百分比,每次young gc之后,就会涨,直到OOM,或者不OOM,但是卡在快满的情况下。

 

7,-gccause   与-gcutil一样,多2列输出导致上次gc的原因

jstat -gccause 64363 1s 100

  • LGCC:上次gc的原因(last gc cause)
  • GCT:Total garbage collection time.(gc cause)

还是差不多,eden区,使用百分比一路上升到百分百的时候,对象没地方分配空间了,就触发young gc,上次gc的原因,就是 Allocation Failure 分配空间失败。

垃圾回收还会有其它原因吗?

比如,我们通过代码显示调用System.gc(),是不是可以手动的告诉jvm gc一下,还有不少其它的方法,我也不知道。。。

 

8,-gcnew 统计新生代的gc情况

jstat -gcnew 64363 1s 100

  • S0C:第一个幸存区大小
  • S1C:第二个幸存区的大小
  • S0U:第一个幸存区的使用大小
  • S1U:第二个幸存区的使用大小
  • TT:对象在新生代存活的次数 (Tenuring threshold.)
  • MTT:对象在新生代存活的最大次数(Maximum tenuring threshold.)
  • DSS:期望的幸存区大小(Desired survivor size (kB).)
  • EC:伊甸园区的大小
  • EU:伊甸园区的使用大小
  • YGC:年轻代垃圾回收次数
  • YGCT:年轻代垃圾回收消耗时间

这些新参数TT MTT DSS 估计和jvm的新生代的设计有关系了,暂时看不出门道来。

上图发生来young gc,时间大概0.003秒

 

9, -gcnewcapacity 类似 -gcnew,关系new区的各个最大和最新空间

jstat -gcnewcapacity 64363 1s 100

  • NGCMN:新生代最小容量
  • NGCMX:新生代最大容量
  • NGC:当前新生代容量
  • S0CMX:最大幸存1区大小
  • S0C:当前幸存1区大小
  • S1CMX:最大幸存2区大小
  • S1C:当前幸存2区大小
  • ECMX:最大伊甸园区大小
  • EC:当前伊甸园区大小
  • YGC:年轻代垃圾回收次数
  • FGC:对堆内存整体包含新生代,老年代,永久代)回收次数

上面看到新生的最大最小设置一样,几个区的容量都是定值,不带变化的。

新生代大小 = s0 + s1 + eden = new区

上面截图中发生了gc的,但是gc跟new区的几个子分区的容量是不会有关系的。

 

10,-gcold 统计old区,堆里面老年代的gc情况

jstat -gcold 64363 1s 100

  • MC:元空间大小
  • MU:元空间使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • YGC:年轻代垃圾回收次数
  • FGC:对堆内存整体包含新生代,老年代,永久代)垃圾回收次数
  • FGCT:对堆内存整体包含新生代,老年代,永久代)垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

最终没被回收的对象都在堆的老年代里面,看老年代的已经使用的大小,再考虑考虑自己代码里面不回收的对象的大小,会不会把这个地方占满,会不会占这么大的空间。可以大致目测一下对象个数。推测这个区的占用是否合理,来判断代码是不是内存泄露了。不过,这个太难了,堆里面又不是只分你的对象,还有不少其它jar包自带的

 

11,-gcoldcapacity 统计old区的各个分区的容量最大最小情况

 jstat -gcoldcapacity 64363 1s 100

  • OGCMN:老年代最小容量
  • OGCMX:老年代最大容量
  • OGC:当前老年代大小
  • OC:老年代大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

好像也没啥,就是看看各个区的大小,这个截图里面old区的最大最小当前实际都是一个值。

 

12,-gcpermcapacity 被 -gcmetacapacity 替代,看元空间的gc情况

jstat -gcmetacapacity 64363 1s 100

  • MCMN: 最小元数据容量
  • MCMX:最大元数据容量
  • MC:当前元数据空间大小
  • CCSMN:最小压缩类空间大小
  • CCSMX:最大压缩类空间大小
  • CCSC:当前压缩类空间大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

他当时写那本书的时候,还在jdk1.6呢,在1.8之后jvm中内存分区有变化了,方法区变成了元空间。

当时说方法区的gc回收效果并不可观,没有堆的gc那么可观,一次gc回收 80%的空间。

估计一般gc都是主要看堆,看堆的 new 和old,重点都在old区。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_27093465/article/details/106524222
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 01:18:50
  • 阅读 ( 529 )
  • 分类:前端

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢