Skip to content

Latest commit

 

History

History
 
 

vjmxcli

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

1. 概述

在cmdline-jmxclient项目上定制,增加功能

  • 支持以pid接入JVM,不需要原JVM在启动参数中打开了JMX选项
  • 完全模拟jstat -gcutil输出的gcutil,用于jstat不能使用的情况, 或者jstat计算使用百分比时,用“已申请大小”,而不是“Max大小”作为分母,不能反映内存是否真正不足的情况。

因为每调度一次java -jar vjmxclient.jar,其实是创建了一个新的JVM,因此在vjmxcli.sh 加上了一系列JVM参数减少消耗。

Download vjmxcli-1.0.8.zip

必须与目标JVM使用相同的JDK版本运行。

2. 获取MBean属性值

// 以host:port接入
./vjmxcli.sh - 127.0.0.1:8060 java.lang:type=Memory HeapMemoryUsage

// 以pid接入
./vjmxcli.sh - 98583 java.lang:type=Memory HeapMemoryUsage

参数解释

  • - : 无密码
  • 127.0.0.1:8060 or 98582 : 应用地址及jmx端口, 或pid
  • java.lang:type=Memory:MBean名
  • HeapMemoryUsage:Attribute名

3. 模拟并改进jstat gcutil输出

jstat有时候会不可使用,比如目标JVM使用-Djava.tmp.dir 重定义了临时目录,或者使用了-XX:+PerfDisableSharedMem禁止了perfdata。此时,可以用vjmxcli代替jstat。

另一种情况,jstat中的分母是已申请的内存,而不是允许的最大内存,因此如果按此百分比进行内存不足的告警,会造成大量误报,比如该区当前使用了95M内存,当前申请内存是100M,而最大内存其实是1G的情况,就不应该促发该区内存使用量超过了90%的告警。

因此vjmxCli的算法是,如果有设置该区内存的最大值,使用最大值做分母,没有设置时才使用该区已申请内存。

为什么jstat不是这样算呢?因为如果Max未设置时,从JMX会返回-1, 而PerfData则会返回一个很没准的大值,因此只读PerfData的jstat完全无法使用Max值做计算。

//一次性输出
./vjmxcli.sh - 127.0.0.1:7001 gcutil

//间隔5秒连续输出
./vjmxcli.sh - 127.0.0.1:7001 gcutil 5

// 以pid连入,间隔5秒连续输出
./vjmxcli.sh - 98583 gcutil 5


JDK7 示例输出

S	      S	      E	     O	     P	   	YGC	YGCT	FGC	FGCT	GCT	
41.25	41.25	2.25	0.00	0.48	2	0.025	0	0.0	   0.025

JDK8 示例输出

S	      S	      E	     O	      M	   CCS	YGC	YGCT	FGC	FGCT	GCT	
41.25	41.25	2.25	0.00	0.48	0	2	0.025	0	0.0	   0.025

4. 附录

4.1 常用JMX条目

条目 Object Name Attribute Name
堆内存 java.lang:type=Memory HeapMemoryUsage
非堆内存(不包含堆外内存) java.lang:type=Memory NonHeapMemoryUsage
堆外内存(不包含新版Netty申请的堆外内存) java.nio:type=BufferPool,name=direct MemoryUsed
线程数 java.lang:type=Threading ThreadCount
守护线程数 java.lang:type=Threading DaemonThreadCount
分代内存及GC 不同JDK的值不一样 不同JDK的值不一样

4.2 启用JMX的启动参数

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=7001  
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=127.0.0.1

以pid连入时不需要预先定义上述参数