目录
1.JDK的命令行工具
1.1 常用工具
名称 |
作用 |
---|---|
jps |
JVM Process Status Tool,显示系统中所有的Hotspot虚拟机进程 |
jstat |
JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据 |
jinfo |
Configuration info for java,显示虚拟机配置信息 |
jmap |
Memory Map for java,生成虚拟机的内存转储快照(heapdump文件) |
jhat |
JVM Heapdump Browser,用于分析heapdump文件,会建立一个HTTP/HTML服务器,用户可以在浏览器上查看分析结果 |
jstack |
Stack Trace for java,显示虚拟机的线程快照 |
1.2 jps:虚拟机进程状况工具
JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程,类似于Linux中的ps命令。
$ jps -help usage: jps [-help] jps [-q] [-mlvV] [<hostid>] Definitions: <hostid>: <hostname>[:<port>]
参数含义:
[xxxx@xxxxx01 ~]$ jps 25052 Bootstrap 13210 Jps [xxxx@xxxxx01 ~]$ jps -q //仅输出虚拟机进程id 25052 13269 [xxxx@xxxxx01 ~]$ jps -m //输出虚拟机进程启用的时候传递给主类main()函数的参数 25052 Bootstrap 13284 Jps -m [xxxx@xxxxx01 ~]$ jps -l //输出主类的全类名 25052 com.xxxx.boot.Bootstrap 13309 sun.tools.jps.Jps [xxxx@xxxxx01 ~]$ jps -v //输出虚拟机进程启动时JVM参数 25052 Bootstrap -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false -Xmx2g -Xms128m -XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/logs/leaf.oom.log -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/xxx.gc -XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -Xloggc:/var/xxx/logs/xxx.gc.log -XX:ErrorFile=/var/xxx/logs/xxx.vmerr.log -XX:HeapDumpPath=/var/xxx/logs/xxx.heaperr.log -Djetty.context=/ -Djetty.logs=/var/xxxxx/logs/ -Djetty.webroot=/opt/xxx/yyy -Djetty.port=8080 -DSTOP.PORT=38415 13335 Jps -Dapplication.home=/usr/local/jdk1.7.0_76 -Xms8m [xxxx@xxxxx01 ~]$ jps -V //有啥作用? 25052 Bootstrap 13670 Jps
常用命令:
jps -lmv
[xxxx@xxxxx01 ~]$ jps -lmv 25052 com.xxx.mms.boot.Bootstrap -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false -Xmx2g -Xms128m -XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/logs/leaf.oom.log -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/leaf.gc -XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -Xloggc:/var/logs//.gc.log -XX:ErrorFile=/var/logs//.vmerr.log -XX:HeapDumpPath=/var/logs//.heaperr.log -Djetty.context=/ -Djetty.logs=/var/logs/ -Djetty.webroot=/opt/xxx/leaf -Djetty.port=8080 -DSTOP.PORT=38415 13685 sun.tools.jps.Jps -lmv -Dapplication.home=/usr/local/jdk1.7.0_76 -Xms8m
1.3 jstat:虚拟机统计信息监控工具
用于监视虚拟机各种运行状态信息的工具。包括类装载、内存、垃圾收集、JIT编译等运行数据。
[xxxx@xxxxx01 ~]$ jstat -help Usage: jstat -help|-options jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] Definitions: <option> An option reported by the -options option <vmid> Virtual Machine Identifier. A vmid takes the following form: <lvmid>[@<hostname>[:<port>]] Where <lvmid> is the local vm identifier for the target Java virtual machine, typically a process id; <hostname> is the name of the host running the target Java virtual machine; and <port> is the port number for the rmiregistry on the target host. See the jvmstat documentation for a more complete description of the Virtual Machine Identifier. <lines> Number of samples between header lines. <interval> Sampling interval. The following forms are allowed: <n>["ms"|"s"] Where <n> is an integer and the suffix specifies the units as milliseconds("ms") or seconds("s"). The default units are "ms". <count> Number of samples to take before terminating. -J<flag> Pass <flag> directly to the runtime system. [xxxx@xxxxx01 ~]$ jstat -options
命令格式:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] //option //vmid //查询间隔 //查询次数 -t参数可以在输出信息前加一个timestamp列,显示程序的运行时间 -h参数可以在周期性数据输出时,输出多少行数据后,跟着输出一个表头信息。 -interval参数用于指定统计数据的输出周期,单位是毫秒 -count参数用于指定输出的次数
把options按功能划分一下
-class //显示ClassLoader相关信息。 监视类装载、卸载数量、总空间以及类装载所花的时间 -gc //显现与GC相关的堆信息。 监视Java堆状况,包括Eden区、两个Survior区、老年代、永久代等容量、已用空间、GC时间统计等信息 -gccapacity //显示各个代的容量和使用情况。 监视内容与-gc基本相同,但是输出主要关注Java堆各个区域使用的最大、最小空间 -gcutil //显示垃圾收集信息。 监视内容与-gc基本相同,但是输出主要关注已使用空间占总空间的百分比 -gccause //显示垃圾收集信息(同-gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因。 -gcnew //显示新生代信息。 监视新生代GC情况 -gcnewcapacity //显示新生代大小与使用情况。 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间 -gcold //显示老年代信息。 监视老年代GC情况 -gcoldcapacity //显示老年代大小与使用使用。 监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间 -gcpermcapacity //输出永久代使用到的最大、最小空间 -compiler //显示JIT编译的相关信息。 输出JIT编译期编译过的方法、耗时等信息 -printcompilation //输出已经被JIT编译过的方法
-class参数
[xxxx@xxxxx01 ~]$ jstat -class 25052 100ms 5 Loaded Bytes Unloaded Bytes Time 9285 18916.1 0 0.0 8.54 9285 18916.1 0 0.0 8.54 9285 18916.1 0 0.0 8.54 9285 18916.1 0 0.0 8.54 9285 18916.1 0 0.0 8.54 Loaded:载入类的数量 Bytes:载入类的合计大小 Unloaded:卸载类的数量 Bytes:卸载类的合计大小 Time:加载类和卸载类上花费的时间
[xxxx@xxxxx01 ~]$ jstat -gc 25052 100ms 5 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 4352.0 4352.0 0.0 496.2 34944.0 18208.5 94960.0 60879.8 262144.0 57052.6 12987 54.255 268 1.606 55.861 4352.0 4352.0 0.0 496.2 34944.0 18208.5 94960.0 60879.8 262144.0 57052.6 12987 54.255 268 1.606 55.861 4352.0 4352.0 0.0 496.2 34944.0 18208.5 94960.0 60879.8 262144.0 57052.6 12987 54.255 268 1.606 55.861 4352.0 4352.0 0.0 496.2 34944.0 18208.5 94960.0 60879.8 262144.0 57052.6 12987 54.255 268 1.606 55.861 4352.0 4352.0 0.0 496.2 34944.0 18208.5 94960.0 60879.8 262144.0 57052.6 12987 54.255 268 1.606 55.861 S0C:年轻代中第一个survivor(幸存区)的容量 (KB) S1C:年轻代中第二个survivor(幸存区)的容量 (KB) S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (KB) S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (KB) EC:年轻代中Eden(伊甸园)的容量 (KB) EU:年轻代中Eden(伊甸园)目前已使用空间 (KB) OC:Old代的容量 (KB) OU:Old代目前已使用空间 (KB) PC:Perm(持久代)的容量 (KB) PU:Perm(持久代)目前已使用空间 (KB) YGC:从应用程序启动到采样时年轻代中gc次数 YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) FGC:从应用程序启动到采样时old代(全gc)gc次数 FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) GCT:从应用程序启动到采样时gc用的总时间(s)
-gccapacity参数
[xxxx@xxxxx01 ~]$ jstat -gccapacity 25052 100ms 5 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC 43648.0 340736.0 43648.0 4352.0 4352.0 34944.0 87424.0 1756416.0 94960.0 94960.0 262144.0 262144.0 262144.0 262144.0 12989 268 43648.0 340736.0 43648.0 4352.0 4352.0 34944.0 87424.0 1756416.0 94960.0 94960.0 262144.0 262144.0 262144.0 262144.0 12989 268 43648.0 340736.0 43648.0 4352.0 4352.0 34944.0 87424.0 1756416.0 94960.0 94960.0 262144.0 262144.0 262144.0 262144.0 12989 268 43648.0 340736.0 43648.0 4352.0 4352.0 34944.0 87424.0 1756416.0 94960.0 94960.0 262144.0 262144.0 262144.0 262144.0 12989 268 43648.0 340736.0 43648.0 4352.0 4352.0 34944.0 87424.0 1756416.0 94960.0 94960.0 262144.0 262144.0 262144.0 262144.0 12989 268 NGCMN:年轻代(young)中初始化(最小)的大小 (KB) 【New Generation Capacity Min】 NGCMX:年轻代(young)的最大容量 (KB) NGC:年轻代(young)中当前的容量 (KB) OGCMN:old代中初始化(最小)的大小 (KB) OGCMX:old代的最大容量 (KB) PGCMN:perm代中初始化(最小)的大小 (KB) PGCMX:perm代的最大容量 (KB)
-gcutil参数
[xxxx@xxxxx01 ~]$ jstat -gcutil 25052 100ms 5 S0 S1 E O P YGC YGCT FGC FGCT GCT 5.52 0.00 73.20 64.11 21.76 12990 54.264 268 1.606 55.870 5.52 0.00 73.20 64.11 21.76 12990 54.264 268 1.606 55.870 5.52 0.00 73.20 64.11 21.76 12990 54.264 268 1.606 55.870 5.52 0.00 73.20 64.11 21.76 12990 54.264 268 1.606 55.870 5.52 0.00 73.20 64.11 21.76 12990 54.264 268 1.606 55.870 S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 E:年轻代中Eden(伊甸园)已使用的占当前容量百分比 O:old代已使用的占当前容量百分比 P:perm代已使用的占当前容量百分比
-gccause参数
[xxxx@xxxxx01 ~]$ jstat -gccause 25052 100ms 5 S0 S1 E O P YGC YGCT FGC FGCT GCT LGCC GCC 4.74 0.00 57.65 64.11 21.76 12992 54.272 268 1.606 55.878 Allocation Failure No GC 4.74 0.00 57.65 64.11 21.76 12992 54.272 268 1.606 55.878 Allocation Failure No GC 4.74 0.00 57.69 64.11 21.76 12992 54.272 268 1.606 55.878 Allocation Failure No GC 4.74 0.00 57.69 64.11 21.76 12992 54.272 268 1.606 55.878 Allocation Failure No GC 4.74 0.00 57.70 64.11 21.76 12992 54.272 268 1.606 55.878 Allocation Failure No GC LGCC:上次GC的原因【Last GC Cause】 GCC:当前GC的原因
-gcnew参数
[xxxx@xxxxx01 ~]$ jstat -gcnew 25052 100ms 5 S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT 4352.0 4352.0 357.9 0.0 15 15 2176.0 34944.0 8722.8 12996 54.285 4352.0 4352.0 357.9 0.0 15 15 2176.0 34944.0 8736.6 12996 54.285 4352.0 4352.0 357.9 0.0 15 15 2176.0 34944.0 8736.6 12996 54.285 4352.0 4352.0 357.9 0.0 15 15 2176.0 34944.0 8736.6 12996 54.285 4352.0 4352.0 357.9 0.0 15 15 2176.0 34944.0 8736.6 12996 54.285 TT:新生代对象晋升到老年代的年龄。Tenuring threshold(提升阈值) MTT:新生代对象晋升到老年代的年龄的最大值。最大的tenuring threshold DSS:所需的Survivor大小。survivor区域大小 (KB)
-gcnewcapacity
[xxxx@xxxxx01 ~]$ jstat -gcnewcapacity 25052 100ms 5 NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC 43648.0 340736.0 43648.0 34048.0 4352.0 34048.0 4352.0 272640.0 34944.0 12997 268 43648.0 340736.0 43648.0 34048.0 4352.0 34048.0 4352.0 272640.0 34944.0 12997 268 43648.0 340736.0 43648.0 34048.0 4352.0 34048.0 4352.0 272640.0 34944.0 12997 268 43648.0 340736.0 43648.0 34048.0 4352.0 34048.0 4352.0 272640.0 34944.0 12997 268 43648.0 340736.0 43648.0 34048.0 4352.0 34048.0 4352.0 272640.0 34944.0 12997 268 S0CMX:最大的S0空间 (KB) S1CMX:最大的S1空间(KB) ECMX:最大eden空间 (KB)
-compiler
[xxxx@xxxxx01 ~]$ jstat -compiler 25052 100ms 5 Compiled Failed Invalid Time FailedType FailedMethod 3093 0 0 34.14 0 3093 0 0 34.14 0 3093 0 0 34.14 0 3093 0 0 34.14 0 3093 0 0 34.14 0 Compiled:编译任务执行的次数 Failed:编译失败的次数 Invalid:编译不可用的次数 FailedType:最后一次编译失败的类型 FailedMethod:最后一次编译失败的类名和方法名
-printcompilation参数
[xxxx@xxxxx01 ~]$ jstat -printcompilation 25052 100ms 5 Compiled Size Type Method 3093 2036 1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next 3093 2036 1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next 3093 2036 1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next 3093 2036 1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next 3093 2036 1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next Compiled:编译任务执行的次数 Size:方法字节码的字节数 Type:编译类型 Method:编译方法的类名和方法名。类名使用”/” 代替 “.” 作为空间分隔符. 方法名是给出类的方法名. 格式是同HotSpot - XX:+PrintComplation选项一致
1.4 jinfo:java配置信息查看工具
jinfo(JVM Configuration info)这个命令作用是实时查看和调整虚拟机运行参数,甚至支持在运行时修改部分参数。
jps -v命令只能查看到显示指定的参数,如果想要查看未被显示指定的参数的值就要使用jinfo口令
$ jinfo Usage: jinfo [option] <pid> (to connect to running process) jinfo [option] <executable <core> (to connect to a core file) jinfo [option] [server_id@]<remote server IP or hostname> (to connect to remote debug server) 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 //不管用 -sysprops to print Java system properties //不管用 <no option> to print both of the above //不管用 -h | -help to print this help message
jinfo命令格式:
jinfo [option] [args] LVMID
option如下
-flag <name>:打印JVM指定参数值 -flag [+|-]<name>:设置指定JVM参数的布尔值 -flag <name>=<value>:设置指定JVM参数的值
使用示例:
1.查看参数值
[xxxx@xxxxx01 ~]$ jinfo -flag SurvivorRatio 66636 -XX:SurvivorRatio=8
2.修改参数值
[xxxx@xxxxx01 ~]$ jinfo -flag +PrintGCDetails 66636
1.5 jmap:Java内存映射工具
jmap(Memory Map for Java)命令用于生成堆转储快照heapdump。
如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候生成。
$ jmap Usage: jmap [option] <pid> (to connect to running process) jmap [option] <executable <core> (to connect to a core file) jmap [option] [server_id@]<remote server IP or hostname> (to connect to remote debug server) where <option> is one of: <none> to print same info as Solaris pmap -heap to print java heap summary -histo[:live] to print histogram of java object heap; if the "live" suboption is specified, only count live objects -permstat to print permanent generation statistics -finalizerinfo to print information on objects awaiting finalization -dump:<dump-options> to dump java heap in hprof binary format dump-options: live dump only live objects; if not specified, all objects in the heap are dumped. format=b binary format file=<file> dump heap to <file> Example: jmap -dump:live,format=b,file=heap.bin <pid> -F force. Use with -dump:<dump-options> <pid> or -histo to force a heap dump or histogram when <pid> does not respond. The "live" suboption is not supported in this mode. -h | -help to print this help message -J<flag> to pass <flag> directly to the runtime system
jmap命令格式:jmap [option] <pid>
option参数如下:
dump : 生成堆转储快照 finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象 heap : 显示Java堆详细信息 histo : 显示堆中对象的统计信息 permstat : to print permanent generation statistics F : 当-dump没有响应时,强制生成dump快照
常用命令
1.生成dump文件
jmap -dump:live,format=b,file=<filename> pid //dump堆到文件,format=b指定输出格式为二进制知识,live指明是活着的对象,file指定文件名
使用示例:
[xxxx@xxxxx01 ~]$ jmap -dump:live,format=b,file=dump.hprof 25052 Dumping heap to /home/xxxx/dump.hprof ... Heap dump file created
2. 输出堆的概要信息
jmap -heap pid
[xxxx@xxxxx01 ~]$ jmap -heap 25052 Attaching to process ID 25052, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.76-b04 using parallel threads in the new generation. using thread-local object allocation. Concurrent Mark-Sweep GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 2147483648 (2048.0MB) NewSize = 1310720 (1.25MB) MaxNewSize = 348913664 (332.75MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 268435456 (256.0MB) MaxPermSize = 268435456 (256.0MB) G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 43974656 (41.9375MB) used = 37745000 (35.996437072753906MB) free = 6229656 (5.941062927246094MB) 85.83353102296013% used Eden Space: capacity = 39124992 (37.3125MB) used = 37745000 (35.996437072753906MB) free = 1379992 (1.3160629272460938MB) 96.47286317655988% used From Space: capacity = 4849664 (4.625MB) used = 0 (0.0MB) free = 4849664 (4.625MB) 0.0% used To Space: capacity = 4849664 (4.625MB) used = 0 (0.0MB) free = 4849664 (4.625MB) 0.0% used concurrent mark-sweep generation: capacity = 97239040 (92.734375MB) used = 20550976 (19.59893798828125MB) free = 76688064 (73.13543701171875MB) 21.134490838247682% used Perm Generation: capacity = 268435456 (256.0MB) used = 58222856 (55.52564239501953MB) free = 210212600 (200.47435760498047MB) 21.689704060554504% used 20990 interned Strings occupying 2568944 bytes.
3.-histo(histogram 直方图)
打印堆的对象统计,包括对象数、内存大小等等 (因为在dump:live前会进行full gc,如果带上live则只统计活对象,因此不加live的堆大小要大于加live堆的大小 )
[xxxx@xxxxx01 ~]$ jmap -histo:live 25052 | more num #instances #bytes class name ---------------------------------------------- 1: 102722 14750176 <constMethodKlass> 2: 102722 13161600 <methodKlass> 3: 9231 10948488 <constantPoolKlass> 4: 47988 7325624 [C 5: 9226 6761096 <instanceKlassKlass> 6: 7607 6037856 <constantPoolCacheKlass> 7: 32606 3836968 [B 8: 4726 2321712 <methodDataKlass> 9: 46337 1112088 java.lang.String 10: 9936 956392 java.lang.Class 11: 35328 847872 io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry 12: 15365 807448 [[I 13: 13630 805176 [S 14: 18214 582848 java.util.concurrent.ConcurrentHashMap$HashEntry 15: 4182 485760 [Ljava.lang.Object; 16: 10664 426560 java.util.TreeMap$Entry 17: 693 376992 <objArrayKlassKlass> 18: 10739 343648 java.util.HashMap$Entry 19: 4139 331120 java.lang.reflect.Method 20: 2326 282960 [Ljava.util.HashMap$Entry; 21: 9694 232656 java.lang.Long 22: 14327 229232 java.lang.Object 23: 1348 209016 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry; 24: 1716 170496 [I 25: 4052 162080 java.util.LinkedHashMap$Entry
其中,class name是对象类型
B byte C char D double F float I int J long Z boolean [ 数组,如[I表示int[] [L+类名 其他对象
1.6 jhat:虚拟机堆快照分析工具
jhat(JVM Heap Analysis Tool)与jmap配合使用,来分析jmap生成的heapdump。
jhat内置了一个HTTP/HTML服务器,可以在浏览器中查看dump文件的分析结果。
一般不用jhat来分析dump文件,jhat功能比较简陋。
一般会download dump文件到本地,使用Eclipse Memory Analyzer(MAT)等工具进行分析。
$ jhat -help Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file> -J<flag> Pass <flag> directly to the runtime system. For example, -J-mx512m to use a maximum heap size of 512MB -stack false: Turn off tracking object allocation call stack. -refs false: Turn off tracking of references to objects -port <port>: Set the port for the HTTP server. Defaults to 7000 -exclude <file>: Specify a file that lists data members that should be excluded from the reachableFrom query. -baseline <file>: Specify a baseline object dump. Objects in both heap dumps with the same ID and same class will be marked as not being "new". -debug <int>: Set debug level. 0: No debug output 1: Debug hprof file parsing 2: Debug hprof file parsing, no server -version Report version number -h|-help Print this help and exit <file> The file to read For a dump file that contains multiple heap dumps, you may specify which dump in the file by appending "#<number>" to the file name, i.e. "foo.hprof#3". All boolean options default to "true"
常用命令:
jhat <filename>
$ jhat java_pid82395.0001.hprof Reading from java_pid82395.0001.hprof... Dump file created Fri Jan 04 22:45:37 CST 2019 Snapshot read, resolving... Resolving 2043422 objects... Chasing references, expect 408 dots........................................................................................................................................................................................................................................................................................................................................................................................................................ Eliminating duplicate references........................................................................................................................................................................................................................................................................................................................................................................................................................ Snapshot resolved. Started HTTP server on port 7000 Server is ready.
jhat将启动一个http服务器,在浏览器中访问http://localhost:7000/
共提供了上面几个功能。
-
Show all members of the rootset (显示所有rootset)
-
Show instance counts for all classes (including platform)(显示所有类的示例数量,含JVM自身运行相关)
-
Show instance counts for all classes (excluding platform)(显示所有类的实例数量,不含JVM自身运行相关)
-
Show heap histogram (显示堆分布直方图)
-
Show finalizer summary
-
Execute Object Query Language (OQL) query(使用OQL查询)
其中,最常用到的。
(1)Show instance counts for all classes (excluding platform)
(2)Show heap histogram
1.7 jstack:Java堆栈跟踪工具
jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合。
生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
$ jstack -help Usage: jstack [-l] <pid> (to connect to running process) jstack -F [-m] [-l] <pid> (to connect to a hung process) jstack [-m] [-l] <executable> <core> (to connect to a core file) jstack [-m] [-l] [server_id@]<remote server IP or hostname> (to connect to a remote debug server) Options: -F to force a thread dump. Use when jstack <pid> does not respond (process is hung) //强制 -m to print both java and native frames (mixed mode) //如果调用到本地方法的话,可以显示c/c++的堆栈 -l long listing. Prints additional information about locks //除堆栈外,还会显示锁的附加信息 -h or -help to print this help message
jstack命令格式:
jstack [option] vmid
option选项:
-F : 当正常输出请求不被响应时,强制输出线程堆栈 -l : 除堆栈外,显示关于锁的附加信息 -m : 如果调用到本地方法的话,可以显示C/C++的堆栈
常用命令:
jstack -l <pid>
使用示例:
jstack不仅可以输出线程堆栈,还能自动进行死锁检查。
下面演示死锁的发生,线程分别占有lockA和lockB,然后请求对方的锁,导致死锁发生。
public class DeadLockDemo extends Thread { static ReentrantLock lockA = new ReentrantLock(); static ReentrantLock lockB = new ReentrantLock(); private Object myLock; public DeadLockDemo(Object myLock) { this.myLock = myLock; if (myLock == lockA) { this.setName("Thread-hold-lockA"); } if (myLock == lockB) { this.setName("Thread-hold-lockB"); } } @Override public void run() { if (myLock == lockA) { try { lockA.lockInterruptibly();//占有lockA try { Thread.sleep(1000); } catch (Exception e) { } lockB.lockInterruptibly();//请求lockB System.out.println(Thread.currentThread().getName() + "成功获取到lockB"); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + "获取lockB失败"); } finally { if (lockA.isHeldByCurrentThread()) { lockA.unlock(); } if (lockB.isHeldByCurrentThread()) { lockB.unlock(); } } } if (myLock == lockB) { try { lockB.lockInterruptibly();//占有lockB try { Thread.sleep(1000); } catch (Exception e) { } lockA.lockInterruptibly();//请求lockA System.out.println(Thread.currentThread().getName() + "成功获取到lockA"); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + "获取lockA失败"); } finally { if (lockA.isHeldByCurrentThread()) { lockA.unlock(); } if (lockB.isHeldByCurrentThread()) { lockB.unlock(); } } } } public static void main(String[] args) throws InterruptedException{ DeadLockDemo hasLockA = new DeadLockDemo(lockA); DeadLockDemo hasLockB = new DeadLockDemo(lockB); hasLockA.start(); hasLockB.start(); Thread.sleep(100000); } }
然后,dump出线程堆栈。
jstack -l 5665 > jstackout
jstackout文件内容如下:
2019-01-06 20:14:10 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode): //是否是守护线程, "Attach Listener" #12 daemon prio=9 os_prio=31 tid=0x00007f8070871000 nid=0x1407 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None //线程名 prio是线程优先级 tid是线程id nid是映射到操作系统的线程id "Thread-hold-lockB" #11 prio=5 os_prio=31 tid=0x00007f806f045800 nid=0x5903 waiting on condition [0x000070000857c000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:57) Locked ownable synchronizers://持有的锁(如果不加-l参数,将不打印这部分内容) - <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) "Thread-hold-lockA" #10 prio=5 os_prio=31 tid=0x00007f806f044800 nid=0x5703 waiting on condition [0x0000700008479000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:35) Locked ownable synchronizers: - <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) Found one Java-level deadlock: //发现死锁 ============================= "Thread-hold-lockB": //线程Thread-hold-lockB想要请求0x000000076abadef0,但是已经被Thread-hold-lockA占有了 waiting for ownable synchronizer 0x000000076abadef0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-hold-lockA" "Thread-hold-lockA": waiting for ownable synchronizer 0x000000076abadf20, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-hold-lockB" Java stack information for the threads listed above: =================================================== "Thread-hold-lockB": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:57) "Thread-hold-lockA": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:35) Found 1 deadlock.