JVM 命令行监控工具
①.jinfo 【显示jvm虚拟机的配置信息】
我们先来查下文档jinfo的用法
使用命令man -jinfo查看用户手册
NAME
jinfo - configuration info
SYNOPSIS
jinfo [ option ] pid
jinfo [ option ] executable core
jinfo [ option ] [ server-id@ ] remote-hostname-or-IP
PARAMETERS
Options are mutually exclusive. Option, if used, should follow immediately after the command name. See OPTIONS below.
pid process id for which the configuration info is to be printed. The process must be a Java process. To get a
list of Java processes running on a machine, jps many be used.
executable Java executable from which the core dump was produced.
core core file for which the configuration info is to be printed.
remote-hostname-or-IP
remote debug server's (see jsadebugd) hostname or IP address.
server-id optional unique id, if multiple debug servers are running on the same remote host.
DESCRIPTION
jinfo prints Java configuration information for a given Java process or core file or a remote debug server. Configuration
information includes Java System properties and Java virtual machine command line flags.
NOTE - This utility is unsupported and may or may not be available in future versions of the J2SE SDK. jinfo is not cur-
rently available on Windows platforms or on the Linux Itanium platform.
OPTIONS
<no option> prints both command line flags as well as System properties name, value pairs
-flags prints command line flags as name, value pairs
-sysprops prints JavaSystem properties as name, value pairs
由手册可知,jinfo命令必须指明运行虚拟机进程(Java进程)的pid号,那么我们怎样得知我们的程序运行的pid呢?有两种办法:
- 使用lsof -i:端口号(例如lsof -i:8081)
jianlejundeMBP:~ allan$ lsof -i:8081 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME STS 25301 allan 76u IPv6 0x7664412dd30e5b9d 0t0 TCP localhost:58969->localhost:sunproxyadmin (CLOSE_WAIT) java 31978 allan 52u IPv6 0x7664412dc6198e1d 0t0 TCP *:sunproxyadmin (LISTEN)
这里明显pid为31978的进程即为我们所需要的应用程序pid号
- 使用jvm的命令jps,列出所有使用虚拟机的进程(直接jps或者加个参数 -l )
jianlejundeMBP:~ allan$ jps -l pid 启动的主类名 25301 31978 org.apache.catalina.startup.Bootstrap 32266 sun.tools.jps.Jps
由上可知,31978的pid为我们所需要的进程(Bootstrap为tomcat的启动入口)
获取到Java进程号后,我们接下来分析jinfo的可选参数
- jinfo pid,则会同时列出jvm系统的属性信息和配置信息
- jinfo -flags pid 则只列出配置信息(****)
jianlejundeMBP:~ allan$ jinfo -flags 31978
Attaching to process ID 31978, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.141-b15
**************重点关注************
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=67108864 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=67108864 -XX:OldSize=67108864 -XX:ThreadStackSize=32768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
**************重点关注************
Command line: -Xmx256m -Xms128m -Xmn64m -Xss32m -Dcatalina.base=/Users/allan/Documents/STSworkspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0 -Dcatalina.home=/Users/allan/Documents/tomcat_CRM_trunk/apache-tomcat-8.5.16 -Dwtp.deploy=/Users/allan/Documents/STSworkspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps -Djava.endorsed.dirs=/Users/allan/Documents/tomcat_CRM_trunk/apache-tomcat-8.5.16/endorsed -Dfile.encoding=UTF-8
- jinfo -sysprops pid 将虚拟机进程的System.getProperties()信息打印出来(了解即可)
- jinfo -flag 属性名 pid:获取指定jdk参数名的值(例如 jinfo -flag InitialHeapSize 31978,结果为134217728)
- jinfo -flag name=value pid修改jvm在运行时可以修改的部分参数(jinfo -flag MaxHeapFreeRatio=99 31978)(了解即可)
查看jvm运行时可以动态修改的参数
$ java -XX:+PrintFlagsFinal | grep manageable
② jps【列出所有正在运行的虚拟机进程】
jps -l 输出pid和该进程的启动主类名
jianlejundeMBP:~ allan$ jps -l
33232 org.apache.catalina.startup.Bootstrap
32467
33339 sun.tools.jps.Jps
jps -v 输出jvm启动时的JVM参数
③jstat(监视虚拟机各种运行状态信息,运行期间定位性能问题的首选工具)
他可以显示本地或者远程虚拟机中的类装载、卸载数量、内存、垃圾收集、JIT编译状况等运行时数据。
命令格式:jstat [option vmid [interval [s|ms] [count]]
其中option,vmid为必要项,后面的为可选项,interval表示查询间隔时间(默认单位为毫秒),count表示查询次数,如果省略可选项表示查询一次。
如果想要每隔250毫秒查询一次java堆状况,一共查询10次,命令:jstat -gc 33232 250 10
如果想要每隔2秒查询一次java堆状况,一共查询5次,命令:jstat -gc 33232 2s 5
以下S0指FromSurvivor区,S1指ToSuvivor区
选项 | 作用 | 示例 |
---|---|---|
-class | 监视类装载卸载数量、总时间等 | jianlejundeMBP:~ allan$ jstat -class 33232 Loaded Bytes Unloaded Bytes Time 5586 11087.5 0 0.0 4.10 |
1.类装载数量 2.类的总大小(字节) 3.类卸载数 4.大小 5.类装载所耗费的时间 | ||
-gc | 监视堆状况 | jianlejundeMBP:~ allan$ jstat -gc 33232 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 512.0 512.0 256.0 0.0 64512.0 9040.7 73216.0 19884.9 34608.0 33736.6 4144.0 3904.5 356 0.703 1 0.051 0.754 |
S0C:S0分配的容量(字节)/ S0U:S0已经使用的空间(字节) /EC:Eden区分配的容量/EU:Eden已使用 /OC:老年代容量 /OU:老年代已使用空间/MC:方法区大小分配的容量/CCSC:压缩类空间大小/YGC:程序运行以来共运行MinorGC次数/YGCT:运行MinorGC总耗时 /FGC:程序运行以来共运行MajorGC次数/GCT:所有GC操作总耗时
| ||
-gccapacity | 显示Java堆各个区域的最大、最小空间 | jianlejundeMBP:~ allan$ jstat -gccapacity 33232 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 65536.0 65536.0 65536.0 512.0 512.0 64512.0 65536.0 196608.0 73216.0 73216.0 0.0 1079296.0 34608.0 0.0 1048576.0 4144.0 518 1 |
NGCMN:新生代分配的最小可用空间/NGCMX:新生代分配的最小可用空间 NGCMX/NGC:当前新生代容量/MCMN:最小元数据容量 /MC:当前元数据空间大小/CCSMN:最小压缩类空间大小 | ||
-gcutil | 显示各个区域已使用空间所占百分比 | jianlejundeMBP:~ allan$ jstat -gcutil 33232 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 50.00 50.00 27.30 97.57 94.22 633 1.128 1 0.051 1.178 |
-gccause | 与gcutil基本一致,还显示多一条导致上一次GC的原因 | jianlejundeMBP:~ allan$ jstat -gccause 33232 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC 43.75 0.00 40.01 27.30 97.59 94.22 644 1.143 1 0.051 1.194 Allocation Failure No GC |
-complier | 输出JIT编译器编译过的方法、耗时等信息 | zhoudadadeMBP:~ shoje$ jstat -compiler 33232 Compiled Failed Invalid Time FailedType FailedMethod 3894 1 0 24.11 1 org/apache/tomcat/util/IntrospectionUtils setProperty |
④ jmap (内存映像工具)
主要用于生成堆转储快照,生成dump文件或称为heapdump文件,同时可以查询java堆和永久代的详细信息,如空间使用率,是使用哪种收集器等)
查询手册如下:
NAME
jmap - memory map
SYNOPSIS
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [ server-id@ ] remote-hostname-or-IP
DESCRIPTION
jmap prints shared object memory maps or heap memory details of a given process or core file or remote debug server.
NOTE - This utility is unsupported and may or may not be available in future versions of the J2SE SDK. jmap is not currently available on Windows platforms or on the Linux
Itanium platform.
PARAMETERS
option Options are mutually exclusive. Option, if used, shouldfollow immediately after the command name.
pid process id for which the memory map is to be printed. The process must be a Java process. To get a list of Java processes running on a machine, jps may be used.
executable Java executable from which the core dump was produced.
core core file for which the memory map is to be printed.
remote-hostname-or-IP
remote debug server's (see jsadebugd) hostname or IP address.
server-id optional unique id, if multiple debug servers are running on the same remote host.
OPTIONS
<no option> When no option is used jmap prints shared object mappings. For each shared object loaded in the target VM, start address, the size of the mapping, and the full
path of the shared object file are printed. This is similar to the Solaris pmap utility.
-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>
-heap Prints a heap summary. GC algorithm used, heap configuration and generation wise heap usage are printed.
-histo Prints a histogram of the heap. For each Java class, number of objects, memory size in bytes, and fully qualified class names are printed. VM internal class
names are printed with '*' prefix.
-permstat Prints class loader wise statistics of permanent generation of Java heap. For each class loader, its name, liveness, address, parent class loader, and the number
and size of classes it has loaded are printed.
-h Prints a help message.
-help Prints a help message.
SEE ALSO
pmap(1) jps(1) jsadebugd(1)
jmap的option为可选项,但不接可选项时基本得到的结果参考价值不大,我们这里主要关注三个选项,-heap,-dump,-histo
1.jmap -heap pid
jianlejundeMBP:~ allan$ jmap -heap 35133
Attaching to process ID 35133, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.141-b15(虚拟机版本)
using thread-local object allocation.
Parallel GC with 4 thread(s)(使用何种收集器)
Heap Configuration:(Java堆的配置信息)
MinHeapFreeRatio = 0 (堆使用率小于n时进行收缩)
MaxHeapFreeRatio = 100 (堆使用率大于n时进行扩张,2个参数在Xmx==Xms 的情况下无效)
MaxHeapSize = 268435456 (256.0MB) (最大堆可用空间)
NewSize = 67108864 (64.0MB) (新生代空间大小)
MaxNewSize = 67108864 (64.0MB) (新生代最大可用空间)
OldSize = 67108864 (64.0MB) (老年代可用空间)
NewRatio = 2(设置老年代与新生代的比例,OLD/NEW=2)
SurvivorRatio = 8(设置Eden:S1:S2=8:1:1,这是jvm的默认设置)
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:(堆的内存监控信息)
PS Young Generation
Eden Space:
capacity = 66060288 (63.0MB) (可用空间)
used = 22447528 (21.407630920410156MB) (已使用)
free = 43612760 (41.592369079589844MB) (空闲)
33.980366540333584% used (已使用所占的百分比)
From Space:
capacity = 524288 (0.5MB)
used = 262144 (0.25MB)
free = 262144 (0.25MB)
50.0% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation
capacity = 77594624 (74.0MB)
used = 17072000 (16.2811279296875MB)
free = 60522624 (57.7188720703125MB)
22.00152422930743% used
17747 interned Strings occupying 2199536 bytes.
有上可知,jmap -heap可以获取堆的一些启动参数和内存映像信息以及使用的垃圾收集器
2.jmap -dump[:live,]format=b,file=filename pid
jianlejundeMBP:~ allan$ jmap -dump:live,format=b,file=Documents/mydumpfile.bin 35133
Dumping heap to /Users/shoje/Documents/mydumpfile.bin ...
Heap dump file created
命令的含义为导出jvm的java堆所有存活对象dump文件,以二进制形式输出,拿到这个这个文件后就可以借助外部的可视化监控工具或者其他途径进行堆的分析。
3.jmap -histo:live pid(显示堆中对象统计信息,包括类,实例数据、实例数量、合计容量等)
作为演示,只截取部分信息
num #instances #bytes class name
----------------------------------------------
1: 52125 8561888 [C
2: 50953 1222872 java.lang.String
3: 1070 760600 [B
4: 8022 705936 java.lang.reflect.Method
5: 6084 683624 java.lang.Class
6: 15582 498624 java.util.HashMap$Node
7: 13256 424192 java.util.concurrent.ConcurrentHashMap$Node
8: 6271 376712 [Ljava.lang.Object;
9: 1789 233008 [Ljava.util.HashMap$Node;
10: 6766 216512 java.lang.ref.WeakReference
11: 3658 146320 java.lang.ref.SoftReference
12: 3326 133040 java.util.LinkedHashMap$Entry
13: 7725 123600 java.lang.Object
14: 2790 115416 [Ljava.lang.String;
15: 2757 112008 [I
16: 118 102592 [Ljava.util.concurrent.ConcurrentHashMap$Node;
17: 4041 96984 java.beans.MethodRef
18: 1985 95280 java.util.HashMap
19: 1607 89992 java.beans.MethodDescriptor
20: 3589 86136 java.util.ArrayList
21: 1499 83944 java.util.LinkedHashMap
.
.
.
.
.
.
由该结果可以很清晰的看出哪些实例的数据所占的空间过大。
4.jmap -finalizerinfo pid(显示在F-Queue等待的Finalizer线程执行finalizer方法的对象,了解即可)
⑤jstack(生成虚拟机的线程快照threaddump或javacore)
线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合
作用:生成线程快照的主要目的是定位线程长时间停顿的原因
语法:jstack [-option] pid
下面为使用jstack 35133命令的结果:(前面关于判断存活对象时涉及到Finalizer线程线程)
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fca55839000 nid=0x2e03 in Object.wait() [0x0000700001e04000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000797bda188> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x0000000797bda188> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"main" #1 prio=5 os_prio=31 tid=0x00007fca55806800 nid=0x2503 runnable [0x00007000016ee000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:466)
at org.apache.catalina.startup.Catalina.await(Catalina.java:744)
at org.apache.catalina.startup.Catalina.start(Catalina.java:690)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:355)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:495)
"VM Thread" os_prio=31 tid=0x00007fca5600b000 nid=0x2c03 runnable
"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fca55009000 nid=0x2107 runnable
"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fca56003000 nid=0x2a03 runnable
(java Thread类中增加了getAllStackTraces()方法用于获取虚拟机中所有的StackTraceElement对象)