在cmdline-jmxclient项目上定制,增加功能
- 支持以pid接入JVM,不需要原JVM在启动参数中打开了JMX选项
- 完全模拟
jstat -gcutil
输出的gcutil
,用于jstat不能使用的情况, 或者jstat计算使用百分比时,用“已申请大小”,而不是“Max大小”作为分母,不能反映内存是否真正不足的情况。
因为每调度一次java -jar vjmxclient.jar
,其实是创建了一个新的JVM,因此在vjmxcli.sh 加上了一系列JVM参数减少消耗。
必须与目标JVM使用相同的JDK版本运行。
// 以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
or98582
: 应用地址及jmx端口, 或pidjava.lang:type=Memory
:MBean名HeapMemoryUsage
:Attribute名
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
条目 | 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的值不一样 |
-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连入时不需要预先定义上述参数