JVM额外知识学习

GC日志分析

1
2
0.303: [Full GC (System.gc()) [PSYoungGen: 464K->0K(76288K)] [ParOldGen: 8K->428K(175104K)] 472K->428K(251392K), 
[Metaspace: 3086K->3086K(1056768K)], 0.0058612 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
分析
  1. 0.303:表示 GC发生的时间,从java虚拟机启动以来经过的秒数。

  2. [Full GC (System.gc()) :表示 垃圾收集的停顿类型。有 [GC, [Full , [Full GC(System.gc())类型。 其中,有 [Full 说明GC过程中发生了STW。如果调用了System.gc()方法触发了收集,则显示:[Full GC(System.gc())

  3. [PSYoungGen:表示 GC发生区域。有 [DefNew[Tenured[Perm等类型。 此处显示的区域名称与使用GC的垃圾收集器有关。Serial收集器中的新生代名为“Default New Generation”,所以显示的是“[DefNew”,如果是ParNew收集器,新生代名称就会变为“[ParNew”,意为“Parallel New Generation”。如果采用Parallel Scavenge收集器,那它配套的新生代称为“PSYoungGen”,老年代和永久代同理,名称也是由收集器决定的。
  4. 464K->0K(76288K):表示 GC前该内存区域已使用容量->GC后该内存区域已使用容量(该内存区域总容量)
  1. 472K->428K(251392K):表示GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆总容量)
  2. 0.0058612 secs:表示 该内存区域GC所占用的时间,单位是秒。
  3. [Times: user=0.01 sys=0.00, real=0.00 secs] :此处 user、sys和real与Linux的time命令所输出的时间含义一致,分别代表用户态消耗的CPU时间、内核态消耗的CPU时间和操作从开始到结束所经过的墙钟时间(Wall Clock Time)。CPU时间与墙钟时间的区别是,墙钟时间包括各种非运算的等待耗时,例如等待磁盘I/O、等待线程阻塞,而CPU时间不包括这些耗时,但当系统有多CPU或者多核的话,多线程操作会叠加这些CPU时间,所以读者看到user或sys时间超过real时间是完全正常的。

GC故障排查工具

当应用部署到生成环境后,无论是直接接触物理服务器还是Telnet到服务器上有可能受到限制。通过java提供的用于监控虚拟机和故障处理的工具,我们可以直接在应用程序中实现功能强大的监控分析功能。JDK主要命令行监控工具有:

名称 主要作用
jps JVM Process Status Tool。显示指定系统内所有的HotSpot虚拟机进程
jstat JVM Statistics Monitoring Tool。用于收集HotSpot虚拟机各方面的运行数据
jinfo Configuration Info for Java。显示虚拟机配置信息
jmap Memory Map for Java。生成虚拟机的内存转储快照(headdump文件)
jhat JVM Heap Dump Browser。用于分析heapdump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果
jstack Stack Trace for Java。显示虚拟机的线程快照
工具详解
jps:虚拟机进程状况工具
  • 意义

    可以列出正在运行的虚拟机进程,并显示虚拟机执行主类名称(Main Class,main()函数所在类)以及进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVIMD)。

  • 命令格式

    jps [options] [hostid]

    其中,hostid 为RMI注册表中注册的主机名。options 可选参数有:

选项 作用
-q 只输出LVIMD,省略主类的名称
-m 输出虚拟机进程启动时传递给main()函数的参数
-l 输出主类的全名,如果进程执行的是jar包,输出jar路径
-V 输出主类的简名
-v 输出虚拟机进程启动时的JVM参数
  • 实例
  1. jps -q (只输出所有虚拟机进程ID)

    1
    2
    3
    4
    5
    houlongdeMacBook-Pro:JavaPattern houlong$ jps -q
    22802
    22803
    23125
    11685
  2. jps -m (输出虚拟机进程启动时传递给主类main()函数的参数)

1
2
3
4
5
houlongdeMacBook-Pro:JavaPattern houlong$ jps -m
22802 Launcher /Applications/IntelliJ IDEA.app/Contents/lib/javac2.jar:/Applications/IntelliJ IDEA.app/Contents/lib/snappy-in-java-0.5.1.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jna.jar:/Applications/IntelliJ IDEA.app/Contents/lib/openapi.jar:/Applications/IntelliJ IDEA.app/Contents/lib/oromatcher.jar:/Applications/IntelliJ IDEA.app/Contents/lib/trove4j.jar:/Applications/IntelliJ IDEA.app/Contents/lib/netty-all-4.1.5.Final.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jps-builders.jar:/Applications/IntelliJ IDEA.app/Contents/lib/nanoxml-2.2.3.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jgoodies-forms.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jdom.jar:/Applications/IntelliJ IDEA.app/Contents/lib/asm-all.jar:/Applications/IntelliJ IDEA.app/Contents/lib/protobuf-2.5.0.jar:/Applications/IntelliJ IDEA.app/Contents/lib/rt/jps-plugin-system.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jna-platform.jar:/Applications/IntelliJ IDEA.app/Contents/lib/annotations.jar:/Applica
22803 AppMain com.houlong.java.gc.StackOverFlowTest
11685
23133 Jps -m
  1. jps -l (输出主类的全名)
1
2
3
4
5
houlongdeMacBook-Pro:JavaPattern houlong$ jps -l
22802 org.jetbrains.jps.cmdline.Launcher
22803 com.intellij.rt.execution.application.AppMain
11685
23142 sun.tools.jps.Jps
  1. jps -V (输出主类的简名)
1
2
3
4
5
houlongdeMacBook-Pro:JavaPattern houlong$ jps -V
22802 Launcher
22803 AppMain
11685
23151 Jps
  1. jps -v (输出虚拟机进程启动时JVM参数)
1
2
3
4
5
houlongdeMacBook-Pro:JavaPattern houlong$ jps -v
22802 Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=/Users/houlong/workplace/JavaPattern -Dpreload.config.path=/Users/houlong/Library/Preferences/IntelliJIdea2016.3/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=2464894803496615857 -Dfile.encoding=UTF-8 -Djps.file.types.component.name=FileTypeManager -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2016.3 -Didea.home.path=/Applications/IntelliJ IDEA.app/Contents -Didea.config.path=/Users/houlong/Library/Preferences/IntelliJIdea2016.3 -Didea.plugins.path=/Users/houlong/Library/Application Support/IntelliJIdea2016.3 -Djps.log.dir=/Users/houlong/Library/Logs/IntelliJIdea2016.3/build-log -Djps.fallback.jdk.home=/Applications/IntelliJ IDEA.app/Contents/jdk/Contents/Home/jre -Djps.fallback.jdk.version=1.8.0_112-release -Djava.io.tmpdir=/Users/houlong/Library/Caches/IntelliJIdea2016.3/compile-se
23155 Jps -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home -Xms8m
22803 AppMain -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/houlong/workplace/JavaPattern/headDump.log -Xloggc:/Users/houlong/workplace/JavaPattern/hha.log -Didea.launcher.port=7535 -Didea.launcher.bin.path=/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
11685 -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Xverify:none -XX:ErrorFile=/Users/houlong/java_error_in_idea_%p.log -XX:HeapDumpPath=/Users/houlong/java_error_in_idea.hprof -Xbootclasspath/a:../lib/boot.jar -Xms128m -Xmx1500m -XX:ReservedCodeCacheSize=500m -XX:+UseCompressedOops -XX:MaxPermSize=500m -Djb.vmOptionsFile=/Users/houlong/Library/Preferences/IntelliJIdea2016.3/idea.vmoptions -Didea.java.redist=jdk-bundled -Didea.home.path=/Applications/IntelliJ IDEA.app/Contents -Didea.executable=idea -Didea.paths.selector=IntelliJIdea2016.3
jstat:虚拟机统计信息监控工具
  • 意义

    用于 监视虚拟机各种运行状态信息的命令行工具 。它可以显示本地或者远程虚拟机进程中的类装载,内存,垃圾收集,JIT编译等运行数据。

  • 命令格式

    jstat [-option] [vmid] [interval(间隔时间)/毫秒] [count(查询次数)]

    表示每隔interval时间后,查询count次JVM的相应信息。
    对于命令格式中的 VMID 和 LVMID ,如果是本地虚拟机进程,则二者是一致的;如果是远程虚拟机进程,则 VMID 的格式为:
    [protocol:][//]lvimd[@hostname[:port]/servername]

1
2
jstat -gc 2764 1000 20
表示每1s中查询进程2764的垃圾收集状况,一共查询20次

其中,option可选参数有:

选项 作用
-class 监视类装载,卸载数量,总空间以及类装载所耗费的时间
-gc 监视java堆状况,包括Eden区,两个Survivor区,老年代,方法区等容量,已用空间,GC时间合计等信息
-gccapacity 监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大,最小空间
-gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew 监视新生代GC状况
-gcnewcapacity 监视内容与-gcnew 基本相同,输出主要关注使用到的最大,最小空间
-gcold 监视老年代GC状况
-gcoldcapacity 监视内容与-gcold 基本相同,输出主要关注使用到的最大,最小空间
-gcmetacapacity 监视元数据空间GC状况,输出主要关注使用到的最大,最小空间
-compiler 输出JIT编译器编译过的方法,耗时等信息
-printcompilation 输出已被JIT编译的方法
  • 实例
  1. jstat -class (类加载统计。监视类装载,卸载数量,总空间以及类装载所耗费的时间)
1
2
3
4
5
6
7
8
9
10
11
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -class 22803 1s 2
Loaded Bytes Unloaded Bytes Time
527 1059.7 0 0.0 0.25
527 1059.7 0 0.0 0.25

解释:
Loaded:加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:类装载所耗费的时间
  1. jstat -compiler(编译统计。输出JIT编译器编译过的方法,耗时等信息)
1
2
3
4
5
6
7
8
9
10
11
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -compiler 24528
Compiled Failed Invalid Time FailedType FailedMethod
5454 1 0 30.49 1 org/springframework/core/annotation/AnnotationUtils findAnnotation

解释:
Compiled:编译数量。
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败的方法
  1. jstat -gc(垃圾回收统计。监视java堆状况)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gc 24528 1s 2
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
16896.0 16384.0 0.0 13231.7 248832.0 70339.6 134656.0 27791.6 52696.0 50328.3 7128.0 6696.4 11 0.178 2 0.114 0.291
16896.0 16384.0 0.0 13231.7 248832.0 70339.6 134656.0 27791.6 52696.0 50328.3 7128.0 6696.4 11 0.178 2 0.114 0.291

解释:
S0C:第一个Survivor区的大小
S1C:第二个Survivor区的大小
S0U:第一个Survivor区的使用大小
S1U:第二个Survivor区的使用大小
EC:Eden区的大小
EU:Eden区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:元数据区大小
MU:元数据区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
  1. jstat -gccapacity(堆内存统计。主要关注java堆各个区域使用到的最大,最小空间)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gccapacity 24528 1s 2
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
87040.0 1397760.0 396800.0 16896.0 16384.0 248832.0 175104.0 2796544.0 134656.0 134656.0 0.0 1095680.0 52696.0 0.0 1048576.0 7128.0 11 2
87040.0 1397760.0 396800.0 16896.0 16384.0 248832.0 175104.0 2796544.0 134656.0 134656.0 0.0 1095680.0 52696.0 0.0 1048576.0 7128.0 11 2

解释:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个Survivor区大小
S1C:第二个Survivor区大小
EC:Eden区大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数
  1. jstat -gcutil(总结垃圾回收统计。主要关注java堆各个区域已使用空间占总空间的百分比)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcutil 24528 1s 2
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 80.76 31.80 20.64 95.51 93.94 11 0.178 2 0.114 0.291
0.00 80.76 31.80 20.64 95.51 93.94 11 0.178 2 0.114 0.291

解释:
S0:第一个Survivor区当前使用比例
S1:第二个Survivor区当前使用比例
E:Eden区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
  1. jstat -gccause(总结垃圾回收统计。与-gcutil基本一致,只是额外输出了上次导致GC的原因)
1
2
3
4
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gccause 24528 1s 2
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
0.00 80.76 32.60 20.64 95.51 93.94 11 0.178 2 0.114 0.291 Allocation Failure No GC
0.00 80.76 32.60 20.64 95.51 93.94 11 0.178 2 0.114 0.291 Allocation Failure No GC
  1. jstat -gcnew(新生代垃圾回收统计。监视新生代GC状况)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcnew 24528 1s 2
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
16896.0 16384.0 0.0 13231.7 1 15 16896.0 248832.0 83113.4 11 0.178
16896.0 16384.0 0.0 13231.7 1 15 16896.0 248832.0 83113.4 11 0.178

解释:
S0C:第一个Survivor区大小
S1C:第二个Survivor区的大小
S0U:第一个Survivor区的使用大小
S1U:第二个Survivor区的使用大小
TT:对象在新生代存活的次数
MTT:对象在新生代存活的最大次数
DSS:期望的幸存区大小
EC:Eden区的大小
EU:Eden区的使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
  1. jstat -gcnewcapacity(新生代内存统计。监视新生代GC状况)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcnewcapacity 24528 1s 2
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
87040.0 1397760.0 396800.0 465920.0 16896.0 465920.0 16384.0 1396736.0 248832.0 11 2
87040.0 1397760.0 396800.0 465920.0 16896.0 465920.0 16384.0 1396736.0 248832.0 11 2

解释:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数
  1. jstat -gcold(老年代垃圾回收统计。监视老年代GC状况)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcold  24528 1s 2
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
52696.0 50328.3 7128.0 6696.4 134656.0 27791.6 11 2 0.114 0.291
52696.0 50328.3 7128.0 6696.4 134656.0 27791.6 11 2 0.114 0.291

解释:
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
  1. jstat -gcoldcapacity(老年代内存统计。主要关注使用到的最大,最小空间)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcoldcapacity  24528 1s 2
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
175104.0 2796544.0 134656.0 134656.0 11 2 0.114 0.291
175104.0 2796544.0 134656.0 134656.0 11 2 0.114 0.291

解释:
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
  1. jstat -gcmetacapacity(元数据空间统计。主要关注使用到的最大,最小空间)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -gcmetacapacity 24528 1s 2
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1095680.0 52696.0 0.0 1048576.0 7128.0 11 2 0.114 0.291
0.0 1095680.0 52696.0 0.0 1048576.0 7128.0 11 2 0.114 0.291

解释:
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
  1. jstat -printcompilation(JVM编译方法统计。输出已被JIT编译的方法)
1
2
3
4
5
6
7
8
9
10
houlongdeMacBook-Pro:JavaPattern houlong$ jstat -printcompilation 24528 1s 2
Compiled Size Type Method
5607 21 1 java/util/TreeSet <init>
5607 21 1 java/util/TreeSet <init>

解释:
Compiled:最近编译方法的数量
Size:最近编译方法的字节码数量
Type:最近编译方法的编译类型。
Method:方法名标识。
jinfo:java配置信息工具
  • 意义

    可以 实时查看和调整虚拟机各项参数

  • 命令格式

    jinfo [option] pid

    其中,option可选参数有:

选项 作用
-flag name 打印指定VM标志的值
-flag [+-]name 启用或禁用指定的VM标志
-flag name=value 将指定的VM标志设置为给定的值
-flags 打印所有VM标识的值
-sysprops 打印Java系统属性
no option 打印上述两个,即-flags与-sysprops所有值
  • 实例
  1. jinfo -flags (打印所有VM标识的值)
1
2
3
4
5
6
7
houlongdeMacBook-Pro:JavaPattern houlong$ jinfo -flags 24528
Attaching to process ID 24528, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:MaxNewSize=1431306240 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line: -Dspring.output.ansi.enabled=always -Didea.launcher.port=7532 -Didea.launcher.bin.path=/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
  1. jinfo -flag (打印指定VM标志的值)
1
2
houlongdeMacBook-Pro:JavaPattern houlong$ jinfo -flag InitialHeapSize  24528
-XX:InitialHeapSize=268435456
  1. jinfo -flag [+|-]name (启用或禁用指定的VM标志)
1
2
3
houlongdeMacBook-Pro:JavaPattern houlong$ jinfo -flag -PrintGC 25598

该命令表示去除虚拟机线程25598VM配置中的PrintGC配置

备注:

  • 如果是布尔类型的JVM参数: jinfo -flag [+|-] PID,enable or disable the named VM flag
  • 如果是数字/字符串类型的JVM参数 jinfo -flag = PID,to set the named VM flag to the given value

其中,需要注意的是,并不是所有的VM标识都可以进行动态配置的,比如:

1
2
3
4
5
6
7
8
houlongdeMacBook-Pro:JavaPattern houlong$ jinfo -flag MetaspaceSize=6m 25598
Exception in thread "main" com.sun.tools.attach.AttachOperationFailedException: flag 'MetaspaceSize' cannot be changed

at sun.tools.attach.BsdVirtualMachine.execute(BsdVirtualMachine.java:213)
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实时调整?官方文档有如下描述:

1
2
3
4
Flags marked as manageable are dynamically writeable through the 
JDK management interface (com.sun.management.HotSpotDiagnosticMXBean API) and also through JConsole.

即:标记为manageable的参数或者通过com.sun.management.HotSpotDiagnosticMXBean这个类的接口得到属性,可以进行动态配置
  1. 标记为manageable的Flags

    • Linux环境:java -XX:+PrintFlagsInitial | grep manageable
    • Window环境:java -XX:+PrintFlagsInitial | findstr manageable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
houlongdeMacBook-Pro:JavaPattern houlong$ java -XX:+PrintFlagsInitial | 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}
  1. 通过HotSpotDiagnosticMXBean API
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
public class DiagnosticOptionsTest {

public static void main(String[] args) {
HotSpotDiagnostic mxBean = new HotSpotDiagnostic();
List<VMOption> diagnosticVMOptions = mxBean.getDiagnosticOptions();
for (VMOption vmOption:diagnosticVMOptions){
System.out.println(vmOption.getName() + " = " + vmOption.getValue());
}
}
}

//output
HeapDumpBeforeFullGC = false
HeapDumpAfterFullGC = false
HeapDumpOnOutOfMemoryError = true
HeapDumpPath = /Users/houlong/workplace/JavaPattern/headDump.log
CMSAbortablePrecleanWaitMillis = 100
CMSWaitDuration = 2000
CMSTriggerInterval = -1
PrintGC = true
PrintGCDetails = false
PrintGCDateStamps = false
PrintGCTimeStamps = true
PrintGCID = false
PrintClassHistogramBeforeFullGC = false
PrintClassHistogramAfterFullGC = false
PrintClassHistogram = false
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
PrintConcurrentLocks = false
UnlockCommercialFeatures = false
jmap:java内存映像工具
  • 意义

    用于生成堆转储快照(一般称为heapdump或dump文件)

  • 命令格式

    jmap [option]

    其中,option可选参数有:

选项 意义
-dump 生成java堆转储快照。格式:-dump:[live,]format=b,file= 其中live子参数说明是否只dump出存活的对象
-finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize方法的对象。
-heap 显示java堆详细信息,如使用哪种回收器,参数配置,分代状况等
-histo[:live] 显示堆中对象统计信息。包括类,实例数量,合计容量。live子参数说明是否只统计出存活的对象
-clstats 打印类加载器统计信息
-F 当虚拟机进程对-dump选项或-histo没有响应时,可使用这个选项强制生成dump快照。其中,不支持子参数live。
  • 实例
    1. jmap -dump(生成java堆转储快照)
1
2
3
houlongdeMacBook-Pro:JavaPattern houlong$ jmap -dump:format=b,file=dump.bin 25772
Dumping heap to /Users/houlong/workplace/JavaPattern/dump.bin ...
Heap dump file created
  1. jmap -finalizerinfo(显示在F-Queue中等待Finalizer线程执行finalize方法的对象)
1
2
3
4
5
6
houlongdeMacBook-Pro:JavaPattern houlong$ jmap -finalizerinfo 25772
Attaching to process ID 25772, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
Number of objects pending for finalization: 0
  1. jmap -heap(显示java堆详细信息)
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
houlongdeMacBook-Pro:JavaPattern houlong$ jmap -heap 25772
Attaching to process ID 25772, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
MinHeapFreeRatio = 50
MaxHeapFreeRatio = 100
MaxHeapSize = 4294967296 (4096.0MB)
NewSize = 89128960 (85.0MB)
MaxNewSize = 1431306240 (1365.0MB)
OldSize = 179306496 (171.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 5242880 (5.0MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 5242880 (5.0MB)
G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 67108864 (64.0MB)
used = 5369144 (5.120414733886719MB)
free = 61739720 (58.87958526611328MB)
8.000648021697998% used
From Space:
capacity = 11010048 (10.5MB)
used = 0 (0.0MB)
free = 11010048 (10.5MB)
0.0% used
To Space:
capacity = 11010048 (10.5MB)
used = 0 (0.0MB)
free = 11010048 (10.5MB)
0.0% used
PS Old Generation
capacity = 179306496 (171.0MB)
used = 0 (0.0MB)
free = 179306496 (171.0MB)
0.0% used

879 interned Strings occupying 59648 bytes.
  1. jmap -histo(显示堆中对象信息)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
houlongdeMacBook-Pro:JavaPattern houlong$ jmap -histo 25772

num #instances #bytes class name
----------------------------------------------
1: 575 4214672 [I
2: 4140 501720 [C
3: 1097 272552 [B
4: 2994 71856 java.lang.String
5: 612 69528 java.lang.Class
6: 673 45984 [Ljava.lang.Object;
7: 721 23072 sun.management.Flag
8: 152 10944 java.lang.reflect.Field
9: 261 8352 java.io.File
10: 334 8016 java.lang.Long
11: 321 7704 java.lang.StringBuilder
12: 113 7232 java.net.URL
  1. jmap -clstats(打印类加载器统计信息)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
houlongdeMacBook-Pro:JavaPattern houlong$ jmap -clstats 25772
Attaching to process ID 25772, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.......done.
class_loader classes bytes parent_loader alive? type

<bootstrap> 532 997889 null live <internal>
0x000000076ab3ffa0 0 0 null live sun/misc/Launcher$ExtClassLoader@0x00000007c000fa48
0x000000076ab6d738 35 109079 0x000000076ab3ffa0 live sun/misc/Launcher$AppClassLoader@0x00000007c000f6a0

total = 3 567 1106968 N/A alive=3, dead=0 N/A

解释:
从上面的输出中,我们可以发现:java程序大致都会使用3种类加载器:
1. 启动类加载器(Bootstrap ClassLoader)
2. 扩展类加载器(Extension ClassLoader)
3. 应用程序类加载器(Application ClassLoader)

且类加载器之间的层次关系为:双亲委派模型

双亲委派模型

jhat:虚拟机堆转储快照分析工具
  • 意义

    该命令与jmap搭配使用,用来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。

  • 实例

  1. jhat dump.bin(分析jmap生成的dump文件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
houlongdeMacBook-Pro:JavaPattern houlong$ jhat dump.bin 
Reading from dump.bin...
Dump file created Sun Apr 01 11:21:35 CST 2018
Snapshot read, resolving...
Resolving 15487 objects...
Chasing references, expect 3 dots...
Eliminating duplicate references...
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

//备注:
其中,dump.bin文件是在介绍jmap命令时,执行命令:
jmap -dump:format=b,file=dump.bin 后生成的dump文件。
在使用jhat命令,显示“Server is ready”后,可以在浏览器中访问:http://localhost:7000/ 就可以查看分析结果
jstack:java堆栈跟踪工具
  • 意义

    该命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合。生成线程快照的主要目的是
    定位线程出现长时间停顿的原因,如线程间死锁,死循环等都是导致线程长时间停顿的常见原因。

  • 命令格式

    jstack [option] vmid

    其中,option的可选参数有:

选项 作用
-F 强制线程转储。 在jstack 不响应时使用(进程挂起)
-l 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法的话,可以显示C/C++的堆栈
  • 实例
  1. jstack -l 24528(除堆栈外,额外显示锁信息)
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
houlongdeMacBook-Pro:JavaPattern houlong$ jstack -l  24528
2018-04-01 21:12:02
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.111-b14 mixed mode):

"Attach Listener" #72 daemon prio=9 os_prio=31 tid=0x00007f9eb629e800 nid=0x4d17 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"DestroyJavaVM" #71 prio=5 os_prio=31 tid=0x00007f9eb6b35000 nid=0x1403 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"http-nio-8000-AsyncTimeout" #69 daemon prio=5 os_prio=31 tid=0x00007f9eba3a2000 nid=0xb503 waiting on condition [0x000070001228d000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1133)
at java.lang.Thread.run(Thread.java:745)

Locked ownable synchronizers:
- None

"VM Thread" os_prio=31 tid=0x00007f9eb6818000 nid=0x2e03 runnable

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007f9eb601a000 nid=0x2607 runnable
  1. jstack -F(输出线程堆栈)
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
houlongdeMacBook-Pro:JavaPattern houlong$ jstack -F 25772
Attaching to process ID 25772, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
Deadlock Detection:

No deadlocks found.

Thread 4871: (state = BLOCKED)


Thread 19715: (state = IN_NATIVE)
- java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) @bci=0 (Interpreted frame)
- java.net.AbstractPlainSocketImpl.accept(java.net.SocketImpl) @bci=7, line=409 (Interpreted frame)
- java.net.ServerSocket.implAccept(java.net.Socket) @bci=60, line=545 (Interpreted frame)
- java.net.ServerSocket.accept() @bci=48, line=513 (Interpreted frame)
- com.intellij.rt.execution.application.AppMain$1.run() @bci=13, line=79 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)

Thread 3587: (state = IN_JAVA)
- com.houlong.java.gc.StackOverFlowTest.main(java.lang.String[]) @bci=144, line=52 (Interpreted frame)
- sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) @bci=0 (Interpreted frame)
- sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=100, line=62 (Interpreted frame)
- sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=43 (Interpreted frame)
- java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=56, line=498 (Interpreted frame)
- com.intellij.rt.execution.application.AppMain.main(java.lang.String[]) @bci=170, line=147 (Interpreted frame)

参考文章

jinfo命令详解

java高分局之jstat命令使用

Fork me on GitHub