【尊重原创文章出自:http://www.chepoo.com/java-jvm-command-tools.html】
一、概述程序运行中经常会遇到各种问题,定位问题时通常需要综合各种信息,如系统日志、堆dump文件、线程dump文件、GC日志等。通过虚拟机监控和诊断工具可以帮忙我们快速获取、分析需要的数据,进而提高问题解决速度。 本文将介绍虚拟机常用监控和问题诊断命令工具的使用方法,主要包含以下工具: jps 显示系统中所有Hotspot虚拟机进程 jstat 收集Hotspot虚拟机各方面运行数据 jstack 显示虚拟机的线程栈信息 jinfo 显示虚拟机的配置信息 jmap 用于生成虚拟机的内存快照信息
以上工具的官方文档地址: http://docs.Oracle.com/javase/1.5.0/docs/tooldocs/ 图形化工具如jconsole,jvisualvm将另文介绍。
二、工具介绍1. jpsJVMPRocess Status Tool,该命令用于列出正在运行的虚拟机进程,显示main类的名称和虚拟机进程id。该命令受当前用户的访问权限影响,比如linux下非root用户只列出当前用户启动的虚拟机进程。
命令格式: jps [options] [hostid]
执行示例:
1
2
3
4
$ jps-l3733 sun.tools.jps.Jps3700 com.leanworld.JVMTools
com.leanworld.JVMTools即为上面的示例代码执行类。
常用参数: -l 输出主类全名 -v 输出虚拟机进程启动的jvm参数 -m 输出启动时传递给main函数的参数
2. jstatJVM Statistics Monitoring Tool,用于监控各种运行状态信息的命令。在只有文本控制台的环境中(如企业中的生产环境),该工具非常有用。 可以用来显示系统中类装载、垃圾回收、运行期编译状况等运行数据。
命令格式: jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ] vmid表示虚拟机唯一标识符,如果是本地虚拟机进程,与LVMID一致,通常为本地虚拟机进程号。 interval表示查询间隔时间,count表示查询次数。如果省略interval和count参数,表示查询一次。
执行示例:
1
2
3
4
5
6
$ jstat-gcutil37005004
S0 S1 E O P YGC YGCT FGC FGCT GCT50.000.0060.780.5012.762140.04900.0000.0490.0025.0020.270.5012.762150.04900.0000.0490.0025.0070.910.5012.762150.04900.0000.04950.000.0020.270.5012.762160.04900.0000.049
S0和S1表示Survivor0和Survivor1,E表示新生代Eden,O表示老年代Old,P表示持久代Permanent,以上各参数值表示已使用空间占比。 YGC表示young gc次数,YGCT表示young gc总耗时。FGC表示Full gc次数,FGCT表示full gc总耗时。GCT表示所有gc总耗时时间。
常用参数: class 类装载相关信息. compiler JIT编译器编译过的方法、耗时等. gc java堆信息和垃圾回收状况. gccapacity 关注java堆各个区的最大和最小空间. gccause 类似gcutil,额外输出导致上一次gc的原因. gcnew 新生代gc状况. gcnewcapacity 关注新生代gc使用的最大和最小空间. gcold 老年代gc状况. gcoldcapacity 关注老年代gc使用的最大和最小空间. gcpermcapacity 关注持久代gc使用的最大和最小空间. gcutil 关注已使用空间占总空间比例. printcompilation 输出已经被JIT编译的方法.
3. jstackStack Trace for Java,用于生成虚拟机当前的线程快照信息,包含每一条线程的堆栈信息。该命令通常用于定位线程停顿原因,当出现线程停顿时,可通过stack查看每个线程的堆栈信息,进而分析停顿原因。 命令格式: jstack [ option ] pid
执行示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ jstack37002012-01-3016:36:05
Full thread dump Java HotSpot(TM) Server VM(17.0-b16 mixed mode):
"Attach Listener" daemon prio=10 tid=0xaca16c00 nid=0x1384 waiting on condition[0x00000000]
java.lang.Thread.State: RUNNABLE
"Low Memory Detector" daemon prio=10 tid=0xaca00c00 nid=0x1366 runnable[0x00000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread1" daemon prio=10 tid=0x08e58800 nid=0x1365 waiting on condition[0x00000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread0" daemon prio=10 tid=0x08e56800 nid=0x1364 waiting on condition[0x00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x08e54c00 nid=0x1363 runnable[0x00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x08e39000 nid=0x1361 inObject.wait()[0xac943000]
java.lang.Thread.State: WAITING(on object monitor)
at java.lang.Object.wait(NativeMethod)- waiting on<0xb10e0230>(a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)- locked<0xb10e0230>(a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x08e34400 nid=0x1360 inObject.wait()[0xacb94000]
java.lang.Thread.State: WAITING(on object monitor)
at java.lang.Object.wait(NativeMethod)- waiting on<0xb10e30d0>(a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)- locked<0xb10e30d0>(a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x08d7bc00 nid=0x135a waiting on condition[0xb6a8a000]
java.lang.Thread.State: TIMED_WAITING(sleeping)
at java.lang.Thread.sleep(NativeMethod)
at com.leanworld.JVMTools.createList(JVMTools.java:23)
at com.leanworld.JVMTools.main(JVMTools.java:29)
"VM Thread" prio=10 tid=0x08e31c00 nid=0x135f runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x08d83800 nid=0x135b runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x08d85000 nid=0x135c runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x08d86400 nid=0x135d runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x08d87c00 nid=0x135e runnable
"VM Periodic Task Thread" prio=10 tid=0xaca02c00 nid=0x1367 waiting on condition
JNI global references:854
通过输出信息可以看出当前main线程处于TIMED_WAITING状态,因为执行到示例代码中Thread.sleep(100);这行的缘故。
常用参数: -l 除堆栈外,显示锁的附加信息 -F 当请求不被响应时,强制输出线程堆栈 -m 混合模式,打印java和本地C++调用的堆栈信息
4. jinfo Configuration Info for Java,用于查看和修改虚拟机的各项参数信息。 命令格式: jinfo [ option ] pid
执行示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$jinfo3700
Attaching to process ID5081, please wait...Debugger attached successfully.Server compiler detected.JVM version is17.0-b16
JavaSystemProperties:
java.runtime.name= Java(TM) SERuntimeEnvironment
sun.boot.library.path=/home/learnworld/software/jdk1.6.0_21/jre/lib/i386
java.vm.version=17.0-b16
java.vm.vendor= Sun Microsystems Inc.java.vendor.url= http://java.sun.com/
path.separator=:
java.vm.name= Java HotSpot(TM) Server VM
file.encoding.pkg= sun.io
sun.java.launcher= SUN_STANDARD
user.country= CN
sun.os.patch.level= unknown
java.vm.specification.name= Java Virtual Machine Specification
user.dir=/home/learnworld/workspace/concurrency
java.runtime.version= 1.6.0_21-b06
java.awt.graphicsenv= sun.awt.X11GraphicsEnvironment
java.endorsed.dirs=/home/learnworld/software/jdk1.6.0_21/jre/lib/endorsed
os.arch= i386
java.io.tmpdir=/tmp
line.separator=
...
VM Flags:-Xmn10m-Xms40m-Xmx40m-Dfile.encoding=GBK
-Xbootclasspath:/home/learnworld/software/jdk1.6.0_21/lib/tools.jar
:/home/learnworld/software/jdk1.6.0_21/lib/sa-jdi.jar
:/home/learnworld/software/jdk1.6.0_21/lib/jconsole.jar
:/home/learnworld/software/jdk1.6.0_21/lib/htmlconverter.jar
:/home/learnworld/software/jdk1.6.0_21/lib/dt.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/rt.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/resources.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib
/plugin.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/management-agent.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/jsse.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/jce.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/javaws.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/deploy.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/charsets.jar
:/home/learnworld/software/jdk1.6.0_21/jre/lib/alt-rt.jar
可以看出,该命令可以方便我们查找需要的虚拟机信息,包含System.getProperties()信息。
常用参数: -flag name 打印虚拟机该参数对应的值. -flag [+\-]name 使该参数生效或失效. -flag name=value 修改相应参数的值. -flags 打印传给jvm的参数值. -sysprops 打印System.getProperties()信息.
5. jmap Memory Map for Java,可以产生堆dump文件,查询堆和持久代的详细信息等。 命令格式: jmap [ option ] pid
执行示例:
1
2
3
$ jmap-dump:format=b,file=dump.tmp3700
Dumping heap to/home/learnworld/dump.tmp ...Heap dump file created
上面这个命令生成了dump.tmp这个dump文件。生成的dump文件可以使用Eclipse Memory Analyzer/jhat等工具进行分析。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ jmap-permstat3700
Attaching to process ID3700, please wait...Debugger attached successfully.Server compiler detected.JVM version is17.0-b161355 intern Strings occupying183024 bytes.findingclass loader instances ..Finding object size using Printezis bits and skipping over...done.computing per loader stat ..done.please wait..computing liveness....done.class_loaderclassesbytesparent_loaderalive?type
<bootstrap>3201437208null live<internal>
0xb117025010771200xb11706b8livesun/misc/Launcher$AppClassLoader@0xad34eb70
0xb11706b800null livesun/misc/Launcher$ExtClassLoader@0xad303d40
total=33301514328 N/A alive=3, dead=0 N/A
常用参数:-dump生成堆dump文件,格式为:-dump:[live,]format=b,file=<filename>-heap显示java堆的详细信息,包括垃圾回收期、堆配置和分代信息等-histo显示堆中对象的统计信息,包括类名称,对应的实例数量和总容量-permstat统计持久代中各ClassLoader的统计信息。
三、遇到的问题 我的操作系统为Ubuntu10.10,初次使用jinfo和jmap时出现以下错误: 引用
1
2
Attaching to process ID3538, please wait...Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process
解决方法: 1. echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 该方法在下次重启前有效。
2. 永久有效方法 sudo vi /etc/sysctl.d/10-ptrace.conf 编辑下面这行: kernel.yama.ptrace_scope = 1 修改为: kernel.yama.ptrace_scope = 0 重启系统,使修改生效。 该bug详细信息请参考官方文档: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7050524