JVM 运维实用排障工具
1、jps
用来查看Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程,可以把jps理解为ps的一个子集。
常用参数如下:
-q:忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid
-m:输出传递给main方法的参数,如果是内嵌的JVM则输出为null
-l:输出完全的包名,应用主类名,jar的完全路径名
-v:输出传给jvm的参数
注意: 使用jps 时的运行账户要和JVM 虚拟机启动的账户一致。若启动JVM虚拟机是运行的账户为www,那使用jps指令时,也要使用www 用户去指定。 sudo -u www jps
Example
// 查看已经运行的JVM 进程的实际启动参数
[root@mouse03 bin]# jps -v
38372 Jps -Dapplication.home=/usr/local/jdk -Xms8m
38360 Bootstrap -Djava.util.logging.config.file=/data0/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms4096m -Xmx4096m -XX:PermSize=1024m -XX:MaxPermSize=2048m -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -Dcatalina.base=/data0/tomcat -Dcatalina.home=/data0/tomcat -Djava.io.tmpdir=/data0/tomcat/temp
2、jstack
jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。如果现在运行的java程序呈现hung的状态,jstack是非常有用的。此信息通常在运维的过程中被保存起来(保存故障现场),以供RD们去分析故障。
常用参数如下:
jstack <pid>
jstack [-l] <pid> //长列表. 打印关于锁的附加信息
jstack [-F] <pid> //当’jstack [-l] pid’没有响应的时候强制打印栈信息
Example
// 打印JVM 的堆栈信息,以供问题排查
[root@mouse03 ~]# jstack -F 38360 > /tmp/jstack.log
3、jinfo
可以查看或修改运行时的JVM进程的参数。
常用参数:
jinfo [option] pid
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
Example
// 根据 PID 查看目前分配的最大堆栈
[root@mouse03 ~]# jinfo -flag MaxHeapSize 38360
-XX:MaxHeapSize=4294967296
// 动态更改 JVM 的最大堆栈值
[root@mouse03 ~]# jinfo -flag MaxHeapSize=4294967296 38360
Exception in thread "main" com.sun.tools.attach.AttachOperationFailedException: flag 'MaxHeapSize' cannot be changed
at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:229)
at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:261)
at sun.tools.attach.HotSpotVirtualMachine.setFlag(HotSpotVirtualMachine.java:234)
at sun.tools.jinfo.JInfo.flag(JInfo.java:134)
at sun.tools.jinfo.JInfo.main(JInfo.java:81)
// jinfo 并不能动态的改变所有的JVM 参数。 那到底有哪些参数能够被动态的改变呢?
// java -XX:+PrintFlagsFinal -version 答应JVM 的所有参数
// java -XX:+PrintFlagsFinal -version | grep manageable
[root@mouse03 ~]# java -XX:+PrintFlagsFinal -version | grep manageable
intx CMSAbortablePrecleanWaitMillis = 100 {manageable}
intx CMSTriggerInterval = -1 {manageable}
intx CMSWaitDuration = 2000 {manageable}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
bool HeapDumpOnOutOfMemoryError = false {manageable}
ccstr HeapDumpPath = {manageable}
uintx MaxHeapFreeRatio = 70 {manageable}
uintx MinHeapFreeRatio = 40 {manageable}
bool PrintClassHistogram = false {manageable}
bool PrintClassHistogramAfterFullGC = false {manageable}
bool PrintClassHistogramBeforeFullGC = false {manageable}
bool PrintConcurrentLocks = false {manageable}
bool PrintGC = false {manageable}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCID = false {manageable}
bool PrintGCTimeStamps = false {manageable}
// 也只有以上这些值才能够动态的被改变
[root@mouse03 ~]# jinfo -flag CMSWaitDuration=1900 38360
# 查看, jinfo -flags 查看 JVM 的 flags
[root@mouse03 ~]# jinfo -flags 38360
Attaching to process ID 38360, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b14
Non-default VM flags: -XX:CICompilerCount=2 -XX:CMSWaitDuration=1900 -XX:InitialHeapSize=4294967296 -XX:MaxHeapSize=4294967296 -XX:MaxNewSize=1431633920 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=1431633920 -XX:OldSize=2863333376 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps
Command line: -Djava.util.logging.config.file=/data0/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms4096m -Xmx4096m -XX:PermSize=1024m -XX:MaxPermSize=2048m -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -Dcatalina.base=/data0/tomcat -Dcatalina.home=/data0/tomcat -Djava.io.tmpdir=/data0/tomcat/temp
4、jstat
// 监控JVM 的状态,常用指令:
# jstat -gc 113059 1000 10 // 打印PID 为 113059 JVM 状态,一共打印10次,每次间隔时间为1s(1000ms)
// 注 jstat 的用法超级强大, 我们这里只是列举出列其中一个简单的应用。
Example
# jstat -gc 113059 1000 10
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
195904.0 195904.0 0.0 21610.3 1567680.0 1516721.9 8526272.0 3557507.8 1048576.0 163148.4 2577 92.033 0 0.000 92.033
195904.0 195904.0 23600.9 0.0 1567680.0 142541.6 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 266338.1 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 413941.8 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 642390.6 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 813957.3 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 984223.2 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 1155472.7 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 23600.9 0.0 1567680.0 1399228.5 8526272.0 3558435.8 1048576.0 163148.4 2578 92.060 0 0.000 92.060
195904.0 195904.0 0.0 23866.6 1567680.0 38005.6 8526272.0 3559196.7 1048576.0 163148.4 2579 92.092 0 0.000 92.092
字段意义如下
列名 | 说明 |
---|---|
S0C | 新生代中Survivor space中S0当前容量的大小(KB) |
S1C | 新生代中Survivor space中S1当前容量的大小(KB) |
S0U | 新生代中Survivor space中S0容量使用的大小(KB) |
S1U | 新生代中Survivor space中S1容量使用的大小(KB) |
EC | Eden space当前容量的大小(KB) |
EU | Eden space容量使用的大小(KB) |
OC | Old space当前容量的大小(KB) |
OU | Old space使用容量的大小(KB) |
PC | Permanent space当前容量的大小(KB) |
PU | Permanent space使用容量的大小(KB) |
YGC | 从应用程序启动到采样时发生 Young GC 的次数 |
YGCT | 从应用程序启动到采样时 Young GC 所用的时间(秒) |
FGC | 从应用程序启动到采样时发生 Full GC 的次数 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(秒) |
GCT | T从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
5、jvmtop
以上介绍的jps、jstack、jinfo等都是安装JDK 时自带的系统分析工具,而jvmtop是一款开源的JVM工具。
它的下载地址如下: https://github.com/patric-r/jvmtop
顾名思义,它是一个只针对JVM的工具,展示的方式和unix的top命令相似.
jvmtop 提供了两个视图,一个是概览视图,可以展示出当前机器的所有的 JVM 的情况. 还有一个视图是详情视图,展示一个 JVM 的详细情况.
概览视图
jvmtop.sh
其中,各个字段的意义分别如下:
PID:进程 ID
MAIN-CLASS:main 类的名字
HPCUR:当前被使用的 heap 的大小
HPMAX:最大可用的 heap 的大小
NHCUR:当前被使用的非 heap 大小(比如:perm gen)
NHMAX:最大可用的非 heap 大小
CPU:CPU 的使用情况
GC:消耗在 GC 上的时间比例
VM:JVM 的提供者,大版本号,小版本号,图中的意思是 Apple 提供的 JDK 6U51 版本。
USERNAME:当前的用户名
#T:线程数量
DL:是否有现成发生死锁
详情视图
jvmtop.sh <pid>
其中,各个字段的意义如下:
TID:线程 ID
NAME:线程名
STATE:线程状态
CPU:线程当前的 CPU 占用情况
TOTALCPU:从线程被创建开始总体的 CPU 占用情况
BLOCKBY:阻塞这个线程的线程 ID