1. 概述

性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。
Java作为最流行的编程语言之一,其应用性能诊断一直受到业界广泛关注。可能造成Java应用出现性能问题的因素非常多,例如线程控制、磁盘读写、数据库访问、网络I/O、垃圾收集等。想要定位这些问题,一款优秀的性能诊断工具必不可少。
体会1: 使用数据说明问题,使用知识分析问题,使用工具处理问题。
体会2: 无监控、不调优!

简单命令行工具

刚接触java学习的时候,大家肯定最先了解的两个命令就是javac , java
那么 , 除此之外,还有没有其他的命令可以供我们使用呢?
我们进入到安装jdk中的bin目录,发现还有一系列辅助工具。这些辅助工具用来获取目标JVM不同方面、不同层次的信息,帮助开发人员很好地解决Java应用程序的一些疑难杂症。
查看java 版本Java -version

32,JVM监控及诊断工具-命令行篇 - 图1
需要解压
32,JVM监控及诊断工具-命令行篇 - 图2
解压结果 , 工具的java包
32,JVM监控及诊断工具-命令行篇 - 图3
源码 : https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/jdk.jcmd/share/classes/sun/tools

2. jps:查看正在运行的Java进程

基本情况

jps(Java Process Staflus):显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。
代码 :

  1. package com.cpucode.java.command.tools.jps;
  2. import java.util.Scanner;
  3. /**
  4. * VM options: -Xms100m -Xms100m
  5. * Program arguments: cpuCode
  6. *
  7. * @author : cpucode
  8. * @date : 2021/2/5
  9. * @time : 18:42
  10. * @github : https://github.com/CPU-Code
  11. * @csdn : https://blog.csdn.net/qq_44226094
  12. */
  13. public class ScannerTest {
  14. public static void main(String[] args) {
  15. Scanner scanner = new Scanner(System.in);
  16. String info = scanner.next();
  17. }
  18. }

设置 VM 参数 和 传入参数
32,JVM监控及诊断工具-命令行篇 - 图4
打开 cmd
32,JVM监控及诊断工具-命令行篇 - 图5
说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。

基本语法

查看 jps 帮助 jps -help
32,JVM监控及诊断工具-命令行篇 - 图6

options参数

仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等
jsp -q
32,JVM监控及诊断工具-命令行篇 - 图7
输出应用程序主类的全类名或如果进程执行的是jar包,则输出jar完整路径
jps -l
32,JVM监控及诊断工具-命令行篇 - 图8

  1. C:\Users\cpucode>jps -l
  2. 1668 com.cpucode.java.command.tools.jps.ScannerTest
  3. 9700 org.jetbrains.jps.cmdline.Launcher
  4. 15352
  5. 1816 jdk.jcmd/sun.tools.jps.Jps
  6. 1500 c:\Users\cpucode\.vscode\extensions\redhat.java-0.74.0\server\plugins\org.eclipse.equinox.launcher_1.6.0.v20200915-1508.jar
  7. 1
  8. 2
  9. 3
  10. 4
  11. 5
  12. 6

输出虚拟机进程启动时传递给主类main()的参数

  1. jps -m
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图9

  1. C:\Users\cpucode>jps -m
  2. 3520 Jps -m
  3. 1668 ScannerTest cpuCode
  4. 9700 Launcher
  5. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/netty-buffer-4.1.47.Final.jar;
  6. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/log4j.jar;
  7. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/maven-builder-support-3.6.1.jar;
  8. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/jps-model.jar;
  9. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/maven-artifact-3.6.1.jar;
  10. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/gson-2.8.6.jar;
  11. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/nanoxml-2.2.3.jar;
  12. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/plexus-component-annotations-1.7.1.jar;
  13. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/util.jar;
  14. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/commons-lang3-3.9.jar;
  15. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/plexus-utils-3.2.0.jar;
  16. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/maven-repository-metadata-3.6.1.jar;
  17. D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/lib/maven-resolver
  18. 15352
  19. 1500 org.eclipse.equinox.launcher_1.6.0.v20200915-1508.jar -configuration
  20. c:\Users\cpucode\AppData\Roaming\Code\User\globalStorage\redhat.java\0.74.0\config_win -data
  21. c:\Users\cpucode\AppData\Roaming\Code\User\workspaceStorage\3cfbb11b7c66d8952d43190664300d9b\redhat.java\jdt_ws
  22. 1
  23. 2
  24. 3
  25. 4
  26. 5
  27. 6
  28. 7
  29. 8
  30. 9
  31. 10
  32. 11
  33. 12
  34. 13
  35. 14
  36. 15
  37. 16
  38. 17
  39. 18
  40. 19
  41. 20
  42. 21
  43. 22
  44. 23

列出虚拟机进程启动时的JVM参数
比如:-Xms20m-Xmx50m是启动程序指定的jvm参数

  1. jps -v
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图10

  1. C:\Users\cpucode>jps -v
  2. 1668 ScannerTest -Xms100m -Xms100m
  3. -javaagent:D:\Program Files\JetBrains\IntelliJ
  4. IDEA 2020.2.3\lib\idea_rt.jar=53076:D:\Program Files\JetBrains\IntelliJ
  5. IDEA 2020.2.3\bin -Dfile.encoding=UTF-8
  6. 9700 Launcher -Xmx700m -Djava.awt.headless=true
  7. -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true
  8. -Dpreload.project.path=D:/Date/github/java
  9. -Dpreload.config.path=C:/Users/cpucode/AppData/Roaming/JetBrains/IntelliJIdea2020.2/options
  10. -Dcompile.parallel=false -Drebuild.on.dependency.change=true
  11. -Dio.netty.initialSeedUniquifier=-2106257460310262667
  12. -Dfile.encoding=GBK -Duser.language=zh -Duser.country=CN
  13. -Didea.paths.selector=IntelliJIdea2020.2
  14. -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3
  15. -Didea.config.path=C:\Users\cpucode\AppData\Roaming\JetBrains\IntelliJIdea2020.2
  16. -Didea.plugins.path=C:\Users\cpucode\AppData\Roaming\JetBrains\IntelliJIdea2020.2\plugins
  17. -Djps.log.dir=C:/Users/cpucode/AppData/Local/JetBrains/IntelliJIdea2020.2/log/build-log
  18. -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2020.2.3/jbr
  19. -Djps.fallback.jdk.version=11.0.8 -Dio.netty.noUnsafe=true
  20. -Djava.io.tmpdir=C:/Users/cpucode/AppData/Local/JetBrains/IntelliJIdea2020.2/compile-server/java_e852b51c/_temp_ -Djps.
  21. 15352 exit -Xms128m -Xmx1966m -XX:ReservedCodeCacheSize=240m -XX:+UseConcMarkSweepGC
  22. -XX:SoftRefLRUPolicyMSPerMB=50 -ea
  23. -XX:CICompilerCount=2
  24. -Dsun.io.useCanonPrefixCache=false
  25. -Djdk.http.auth.tunneling.disabledSchemes=""
  26. -XX:+HeapDumpOnOutOfMemoryError
  27. -XX:-OmitStackTraceInFastThrow
  28. -Djdk.attach.allowAttachSelf=true -Dkotlinx.coroutines.debug=off
  29. -Djdk.module.illegalAccess.silent=true
  30. -javaagent:C:\Users\Public\.jetbrains\jetbrains-agent-v3.2.0.0f1f.69e=6e68f9eb,HbVMaxqQrTt4UvDUk8fhyFT7uRdv48bqJsQMwVFp53YH9PZC9l+ZxAgnA60cLwwhURw/e4DcZZtle4tQzur4yWRk35qghES4JLFlmKty/UNiYh6RZyXeCNPTCvIqxT9HR2YKqQT93be6AfLTcbJwPSLO201g+HbMbg6+aK1MUJI
  31. -Djb.vmOptionsFile=
  32. C:\Users\cpucode\AppData\Roaming\JetBrains\IntelliJIdea2020.2\idea64.exe.vmoptions
  33. -Djava.library.path=
  34. D:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3\jbr\\bin;
  35. D:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3\jbr\\bin\server
  36. -Didea.jre.check=true -Dide.native.launcher=true
  37. -Didea.vendor.name=JetBrains
  38. -Didea.paths.selector=IntelliJIdea2020.2
  39. -XX:ErrorFile=C:\Users\c
  40. 15544 Jps -Dapplication.home=D:\Program Files\java\jdk-14.0.2
  41. -Xms8m -Djdk.module.main=jdk.jcmd
  42. 1500 org.eclipse.equinox.launcher_1.6.0.v20200915-1508.jar
  43. --add-modules=ALL-SYSTEM
  44. --add-opens=java.base/java.util=ALL-UNNAMED
  45. --add-opens=java.base/java.lang=ALL-UNNAMED
  46. -Declipse.application=org.eclipse.jdt.ls.core.id1
  47. -Dosgi.bundles.defaultStartLevel=4
  48. -Declipse.product=org.eclipse.jdt.ls.core.product
  49. -Dfile.encoding=utf8 -DwatchParentProcess=false
  50. -XX:+UseParallelGC -XX:GCTimeRatio=4
  51. -XX:AdaptiveSizePolicyWeight=90
  52. -Dsun.zip.disableMemoryMapping=true
  53. -Xmx1G -Xms100m
  54. 1
  55. 2
  56. 3
  57. 4
  58. 5
  59. 6
  60. 7
  61. 8
  62. 9
  63. 10
  64. 11
  65. 12
  66. 13
  67. 14
  68. 15
  69. 16
  70. 17
  71. 18
  72. 19
  73. 20
  74. 21
  75. 22
  76. 23
  77. 24
  78. 25
  79. 26
  80. 27
  81. 28
  82. 29
  83. 30
  84. 31
  85. 32
  86. 33
  87. 34
  88. 35
  89. 36
  90. 37
  91. 38
  92. 39
  93. 40
  94. 41
  95. 42
  96. 43
  97. 44
  98. 45
  99. 46
  100. 47
  101. 48
  102. 49
  103. 50
  104. 51
  105. 52
  106. 53
  107. 54
  108. 55
  109. 56
  110. 57

说明:以上参数可以综合使用。
补充:
如果某Java进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData) , 那么 jps 命令以及 jstat 将无法探知该Java 进程。
设置 VM 参数 和 传入参数
32,JVM监控及诊断工具-命令行篇 - 图11
打开 cmd
32,JVM监控及诊断工具-命令行篇 - 图12

hostid参数

RMI注册表中注册的主机名。
如果想要远程监控主机上的 java 程序,需要安装 jstatd。
对于具有更严格的安全实践的网络场所而言,可能使用一个自定义的策略文件来显示对特定的可信主机或网络的访问,尽管这种技术容易受到IP地址欺诈攻击。
如果安全问题无法使用一个定制的策略文件来处理,那么最安全的操作是不运行jstatd服务器,而是在本地使用jstat和jps工具。

3. jstat:查看JVM统计信息

基本情况

jstat(JVM Statistics Monitoring Tool): 用于监视虚拟机各种运行状态信息的命令行工具。
它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
常用于检测垃圾回收问题以及内存泄漏问题。
官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
32,JVM监控及诊断工具-命令行篇 - 图13

基本语法

它的基本使用语法为:

  1. jstat --help|-options
  2. jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
  3. 1
  4. 2
  5. 3

查看命令相关参数:

  1. jstat -h
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图14

  1. jstat -help
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图15

option参数

选项option可以由以下值构成 :
类装载相关的:
显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等

  1. jstat -class PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图16

  1. C:\Users\cpucode>jstat -class 11916
  2. Loaded Bytes Unloaded Bytes Time
  3. 692 1417.0 0 0.0 0.09
  4. 1
  5. 2
  6. 3

垃圾回收相关的:
代码 :

  1. package com.cpucode.java.command.tools.jstat;
  2. import java.util.ArrayList;
  3. /**
  4. * -Xms60m -Xmx60m -XX:SurvivorRatio=8
  5. *
  6. * @author : cpucode
  7. * @date : 2021/2/5
  8. * @time : 20:28
  9. * @github : https://github.com/CPU-Code
  10. * @csdn : https://blog.csdn.net/qq_44226094
  11. */
  12. public class GCTest {
  13. public static void main(String[] args) {
  14. ArrayList<byte[]> list = new ArrayList<>();
  15. int num = 1000;
  16. for (int i = 0; i < num; i++) {
  17. //100KB
  18. byte[] arr = new byte[1024 * 100];
  19. list.add(arr);
  20. try{
  21. Thread.sleep(100);
  22. }catch (InterruptedException e){
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }
  28. 1
  29. 2
  30. 3
  31. 4
  32. 5
  33. 6
  34. 7
  35. 8
  36. 9
  37. 10
  38. 11
  39. 12
  40. 13
  41. 14
  42. 15
  43. 16
  44. 17
  45. 18
  46. 19
  47. 20
  48. 21
  49. 22
  50. 23
  51. 24
  52. 25
  53. 26
  54. 27
  55. 28
  56. 29
  57. 30
  58. 31

32,JVM监控及诊断工具-命令行篇 - 图17
显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息

  1. jstat -gc PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图18

  1. C:\Users\cpucode>jstat -gc 15672 1000 5
  2. S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT
  3. 2048.0 2048.0 0.0 0.0 16384.0 1808.0 40960.0 29279.5 4864.0 3824.6 512.0 415.6 2 0.010 1 0.013 - - 0.023
  4. 2048.0 2048.0 0.0 0.0 16384.0 2808.1 40960.0 29279.5 4864.0 3824.6 512.0 415.6 2 0.010 1 0.013 - - 0.023
  5. 2048.0 2048.0 0.0 0.0 16384.0 3808.3 40960.0 29279.5 4864.0 3824.6 512.0 415.6 2 0.010 1 0.013 - - 0.023
  6. 2048.0 2048.0 0.0 0.0 16384.0 4808.5 40960.0 29279.5 4864.0 3824.6 512.0 415.6 2 0.010 1 0.013 - - 0.023
  7. 2048.0 2048.0 0.0 0.0 16384.0 5808.6 40960.0 29279.5 4864.0 3824.6 512.0 415.6 2 0.010 1 0.013 - - 0.023
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7
  15. 8

显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间

  1. jstat -gccapacity PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图19

  1. C:\Users\cpucode>jstat -gccapacity 8928 1000 5
  2. NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC
  3. 20480.0 20480.0 20480.0 2048.0 2048.0 16384.0 40960.0 40960.0 40960.0 40960.0 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 2 1 -
  4. 20480.0 20480.0 20480.0 2048.0 2048.0 16384.0 40960.0 40960.0 40960.0 40960.0 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 2 1 -
  5. 20480.0 20480.0 20480.0 2048.0 2048.0 16384.0 40960.0 40960.0 40960.0 40960.0 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 2 1 -
  6. 20480.0 20480.0 20480.0 2048.0 2048.0 16384.0 40960.0 40960.0 40960.0 40960.0 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 2 1 -
  7. 20480.0 20480.0 20480.0 2048.0 2048.0 16384.0 40960.0 40960.0 40960.0 40960.0 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 2 1 -
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示内容与 -gc 基本相同,但输出主要关注已使用空间占总空间的百分比

  1. jstat -gcutil PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图20

  1. C:\Users\cpucode>jstat -gcutil 9012 1000 5
  2. S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT
  3. 0.00 99.82 66.72 28.34 78.57 81.17 1 0.004 0 0.000 - - 0.004
  4. 0.00 99.82 74.06 28.34 78.57 81.17 1 0.004 0 0.000 - - 0.004
  5. 0.00 99.82 80.81 28.34 78.57 81.17 1 0.004 0 0.000 - - 0.004
  6. 0.00 99.82 85.70 28.34 78.57 81.17 1 0.004 0 0.000 - - 0.004
  7. 0.00 99.82 90.60 28.34 78.57 81.17 1 0.004 0 0.000 - - 0.004
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因

  1. jstat -gccause PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图21

  1. C:\Users\cpucode>jstat -gccause 16564 1000 5
  2. S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC
  3. 0.00 99.43 36.61 27.41 78.62 81.17 1 0.004 0 0.000 - - 0.004 Allocation Failure No GC
  4. 0.00 99.43 42.72 27.41 78.62 81.17 1 0.004 0 0.000 - - 0.004 Allocation Failure No GC
  5. 0.00 99.43 48.82 27.41 78.62 81.17 1 0.004 0 0.000 - - 0.004 Allocation Failure No GC
  6. 0.00 99.43 55.54 27.41 78.62 81.17 1 0.004 0 0.000 - - 0.004 Allocation Failure No GC
  7. 0.00 99.43 61.64 27.41 78.62 81.17 1 0.004 0 0.000 - - 0.004 Allocation Failure No GC
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示新生代GC状况

  1. jstat -gcnew PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图22

  1. C:\Users\cpucode>jstat -gcnew 2496 1000 5
  2. S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
  3. 2048.0 2048.0 0.0 2016.2 7 15 2048.0 16384.0 4512.6 1 0.004
  4. 2048.0 2048.0 0.0 2016.2 7 15 2048.0 16384.0 5314.9 1 0.004
  5. 2048.0 2048.0 0.0 2016.2 7 15 2048.0 16384.0 6518.4 1 0.004
  6. 2048.0 2048.0 0.0 2016.2 7 15 2048.0 16384.0 7320.7 1 0.004
  7. 2048.0 2048.0 0.0 2016.2 7 15 2048.0 16384.0 8524.1 1 0.004
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间

  1. jstat -gcnewcapacity PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图23

  1. C:\Users\cpucode>jstat -gcnewcapacity 4648 1000 5
  2. NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC
  3. 20480.0 20480.0 20480.0 2048.0 2048.0 2048.0 2048.0 19456.0 16384.0 1 0 -
  4. 20480.0 20480.0 20480.0 2048.0 2048.0 2048.0 2048.0 19456.0 16384.0 1 0 -
  5. 20480.0 20480.0 20480.0 2048.0 2048.0 2048.0 2048.0 19456.0 16384.0 1 0 -
  6. 20480.0 20480.0 20480.0 2048.0 2048.0 2048.0 2048.0 19456.0 16384.0 1 0 -
  7. 20480.0 20480.0 20480.0 2048.0 2048.0 2048.0 2048.0 19456.0 16384.0 1 0 -
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示老年代GC状况

  1. jstat -gcold PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图24

  1. C:\Users\cpucode>jstat -gcold 5356 1000 5
  2. MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT
  3. 4864.0 3821.9 512.0 415.6 40960.0 11609.8 1 0 0.000 - - 0.006
  4. 4864.0 3821.9 512.0 415.6 40960.0 11609.8 1 0 0.000 - - 0.006
  5. 4864.0 3821.9 512.0 415.6 40960.0 11609.8 1 0 0.000 - - 0.006
  6. 4864.0 3821.9 512.0 415.6 40960.0 11609.8 1 0 0.000 - - 0.006
  7. 4864.0 3821.9 512.0 415.6 40960.0 11609.8 1 0 0.000 - - 0.006
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间

  1. jstat -gcoldcapacity PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图25

  1. C:\Users\cpucode>jstat -gcoldcapacity 6044 1000 5
  2. OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT
  3. 40960.0 40960.0 40960.0 40960.0 1 0 0.000 - - 0.004
  4. 40960.0 40960.0 40960.0 40960.0 1 0 0.000 - - 0.004
  5. 40960.0 40960.0 40960.0 40960.0 2 1 0.011 - - 0.021
  6. 40960.0 40960.0 40960.0 40960.0 2 1 0.011 - - 0.021
  7. 40960.0 40960.0 40960.0 40960.0 2 1 0.011 - - 0.021
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

显示jdk8以前永久代使用到的最大、最小空间

  1. jstat -gcpermcapacity PID
  2. 1

显示 jdk8以后元空间使用到的最大、最小空间

  1. jstat -gcmetacapacity PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图26

  1. C:\Users\cpucode>jstat -gcmetacapacity 17280 1000 5
  2. MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT
  3. 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 1 0 0.000 - - 0.005
  4. 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 1 0 0.000 - - 0.005
  5. 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 1 0 0.000 - - 0.005
  6. 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 1 0 0.000 - - 0.005
  7. 0.0 1056768.0 4864.0 0.0 1048576.0 512.0 1 0 0.000 - - 0.005
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

JIT相关的:
显示JIT编译器编译过的方法、耗时等信息

  1. jstat -compiler PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图27

  1. C:\Users\cpucode>jstat -compiler 11916
  2. Compiled Failed Invalid Time FailedType FailedMethod
  3. 91 0 0 0.04 0
  4. 1
  5. 2
  6. 3

输出已经被JIT编译的方法

  1. jstat -printcompilation PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图28

  1. C:\Users\cpucode>jstat -printcompilation 11916
  2. Compiled Size Type Method
  3. 91 2702 1 java/util/Properties saveConvert
  4. 1
  5. 2
  6. 3

参数细节

新生代相关

  • SOC是第一个幸存者区的大小(字节)
  • S1C是第二个幸存者区的大小(字节)
  • SOU是第一个幸存者区已使用的大小(字节)
  • S1U是第二个幸存者区已使用的大小(字节)
  • EC是Eden空间的大小(字节)
  • EU是Eden空间已使用大小(字节)

老年代相关

  • OU是老年代已使用的大小(字节)
  • OC是老年代的大小(字节)

方法区(元空间)相关

  • MC是方法区的大小
  • MU是方法区已使用的大小
  • CCSC是压缩类空间的大小
  • CCSU是压缩类空间已使用的大小

其它

  • YGC是指从应用程序启动到采样时young gc次数
  • YGCT是指从应用程序启动到采样时young gc消耗的时间(秒)
  • FGC是指从应用程序启动到采样时fullgc次数
  • FGCT是指从应用程序启动到采样时full gc消耗的时间(秒)
  • GCT是指从应用程序启动到采样时gc的总时间

    -t参数

    可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
    1. jstat -class -t PID
    2. 1
    1. jstat -class -t 11916
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图29
    1. C:\Users\cpucode>jstat -class -t 11916
    2. Timestamp Loaded Bytes Unloaded Bytes Time
    3. 369.7 692 1417.0 0 0.0 0.09
    4. 1
    5. 2
    6. 3
    经验
    可以比较 Java 进程的启动时间 以及 总GC 时间( GCT列 ), 或者 两次测量的间隔时间 以及 总GC时间 的增量, 来得出GC时间占运行时间的比例
    如果该比例超过20%, 则说明目前堆的压力较大;
    如果该比例超过90%, 则说明堆里几乎没有可用空间, 随时都可能抛出 OOM 异常

    -h参数

    可以在周期性数据输出时,输出多少行数据后输出一个表头信息
    1. jstat -class -hx PID
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图30
    1. C:\Users\cpucode>jstat -class -t -h3 11916
    2. Timestamp Loaded Bytes Unloaded Bytes Time
    3. 474.2 692 1417.0 0 0.0 0.09
    4. 1
    5. 2
    6. 3

    interval参数

    用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
    1. jstat -class PID s
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图31
    1. C:\Users\cpucode>jstat -class -t -h3 11916 1000
    2. Timestamp Loaded Bytes Unloaded Bytes Time
    3. 746.6 692 1417.0 0 0.0 0.09
    4. 747.7 692 1417.0 0 0.0 0.09
    5. 748.7 692 1417.0 0 0.0 0.09
    6. Timestamp Loaded Bytes Unloaded Bytes Time
    7. 749.6 692 1417.0 0 0.0 0.09
    8. 750.6 692 1417.0 0 0.0 0.09
    9. 751.6 692 1417.0 0 0.0 0.09
    10. Timestamp Loaded Bytes Unloaded Bytes Time
    11. 752.7 692 1417.0 0 0.0 0.09
    12. 753.7 692 1417.0 0 0.0 0.09
    13. 1
    14. 2
    15. 3
    16. 4
    17. 5
    18. 6
    19. 7
    20. 8
    21. 9
    22. 10
    23. 11
    24. 12

    count参数

    用于指定查询的总次数
    1. jstat -class PID s n
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图32
    1. C:\Users\cpucode>jstat -class -t -h3 11916 1000 5
    2. Timestamp Loaded Bytes Unloaded Bytes Time
    3. 770.6 692 1417.0 0 0.0 0.09
    4. 771.6 692 1417.0 0 0.0 0.09
    5. 772.6 692 1417.0 0 0.0 0.09
    6. Timestamp Loaded Bytes Unloaded Bytes Time
    7. 773.6 692 1417.0 0 0.0 0.09
    8. 774.6 692 1417.0 0 0.0 0.09
    9. 1
    10. 2
    11. 3
    12. 4
    13. 5
    14. 6
    15. 7
    16. 8

    补充

    jstat 还可以用来判断是否出现内存泄漏 :
    第1步:
    在长时间运行的 Java 程序中,我们可以运行 jstat 命令连续获取多行性能数据,并取这几行数据中OU列(即已占用的老年代内存)的最小值。
    第2步:
    然后,我们每隔一段较长的时间重复一次上述操作,来获得多组OU最小值。
    如果这些值呈上涨趋势,则说明该Java程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。

    4. jinfo:实时查看和修改JVM配置参数

    基本情况

    jinfo(Configuralion Info for Java) : 查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。
    在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。
    在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。
    官方帮助文档:
    JDK8
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
    JDK11
    https://docs.oracle.com/en/java/javase/11/tools/jinfo.html#GUID-69246B58-28C4-477D-B375-278F5F9830A5

    基本语法

    它的基本使用语法为:
    1. jinfo [ options ] pid
    2. 1
    说明:java进程ID必须要加上
    [options]:
选项 选项说明
no option 输出全部的参数和系统属性
-flag name 输出对应名称的参数
-flag [±]name 开启或者关闭对应名称的参数只有被标记为manageable的参数才可以被动态修改
-flag name=value 设定对应名称的参数
-flags 输出全部的参数
-sysprops 输出系统属性

查看

可以查看由System.getProperties()取得的参数

  1. jinfo -sysprops PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图33
查看曾经赋过值的一些参数

  1. jinfo -flags PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图34

  1. C:\Users\cpucode>jinfo -flags 13476
  2. VM Flags:
  3. -XX:CICompilerCount=12
  4. -XX:InitialHeapSize=257949696
  5. -XX:MaxHeapSize=4125097984
  6. -XX:MaxNewSize=1374683136
  7. -XX:MinHeapDeltaBytes=524288
  8. -XX:NewSize=85983232
  9. -XX:OldSize=171966464
  10. -XX:+UseCompressedClassPointers
  11. -XX:+UseCompressedOops
  12. -XX:-UseLargePagesIndividualAllocation
  13. -XX:+UseParallelGC
  14. 1
  15. 2
  16. 3
  17. 4
  18. 5
  19. 6
  20. 7
  21. 8
  22. 9
  23. 10
  24. 11
  25. 12
  26. 13

查看某个java进程的具体参数的值

  1. jinfo -flag 具体参数 PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图35

  1. C:\Users\cpucode>jinfo -flag UseParallelGC 13476
  2. -XX:+UseParallelGC
  3. C:\Users\cpucode>jinfo -flag UseG1GC 13476
  4. -XX:-UseG1GC
  5. 1
  6. 2
  7. 3
  8. 4
  9. 5

修改

jinfo不仅可以查看运行时某一个Java虚拟机参数的实际取值,甚至可以在运行时修改部分参数,并使之立即生效。
但是,并非所有参数都支持动态修改。参数只有被标记为manageable的flag可以被实时修改。其实,这个修改能力是极其有限的。
可以查看被标记为manageable的参数

  1. java-XX:+PrintFlagsFinal-version|grep manageable
  2. 1
intx CMSAbortablePrecleanWaitMillis =100 {manageable}
intx CMSWaitDuration =2000 {manageable}
bool HeapDumpAfterFullGC =false {manageable}
bool HeapDumpBeforeFullGC =false {manageable}
bool HeapDumpOnOutofMemoryError =false {manageable}
ccstr HeapDumpPath {manageable}
uintx MaxHeapFreeRatio =100 {manageable}
uintx MinHeapFreeRatio =0 {manageable}
bool PrintClassHistogram =false {manageable}
bool PrintClassHistogragAfterFullGC =false {manageable}
bool PrintClassHistogramBeforeFullGC =false {manageable}
bool PrintConcurrentLocks =false {manageable}
bool PrintGC =false {manageable}
bool PrintGCDateStamps =false {manageable}
bool PrintGCDetails =false [manageable}
bool PrintGCTimeStamps =false {manageable}

针对非boolean类型

  1. jinfo -flag 具体参数=具体参数值 PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图36

  1. C:\Users\cpucode>jinfo -flag MaxHeapFreeRatio 13476
  2. -XX:MaxHeapFreeRatio=100
  3. C:\Users\cpucode>jinfo -flag MaxHeapFreeRatio=90 13476
  4. C:\Users\cpucode>jinfo -flag MaxHeapFreeRatio 13476
  5. -XX:MaxHeapFreeRatio=90
  6. 1
  7. 2
  8. 3
  9. 4
  10. 5
  11. 6
  12. 7

针对boolean类型

  1. jinfo -flag [+-]具体参数 PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图37

  1. C:\Users\cpucode>jinfo -flag PrintGC 13476
  2. -XX:-PrintGC
  3. C:\Users\cpucode>jinfo -flag +PrintGC 13476
  4. C:\Users\cpucode>jinfo -flag PrintGC 13476
  5. -XX:+PrintGC
  6. 1
  7. 2
  8. 3
  9. 4
  10. 5
  11. 6
  12. 7

拓展

查看所有JVM参数启动的初始值

  1. java-XX+PrintFlagslnitial PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图38

  1. C:\Users\cpucode>jinfo -XX+PrintFlagsInitial 13476
  2. 1

查看所有NM参数的最终值

  1. java-XX:+PrintFlagsFinal PID
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图39

  1. C:\Users\cpucode>jinfo -XX+PrintFlagsFinal 13476
  2. 1

查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值

  1. java-XX+PrintCommandLineFlags
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图40

  1. C:\Users\cpucode>java -XX:+PrintCommandLineFlags 12132
  2. -XX:InitialHeapSize=16777216
  3. -XX:MaxHeapSize=268435456
  4. -XX:+PrintCommandLineFlags
  5. -XX:-UseLargePagesIndividualAllocation
  6. 错误: 找不到或无法加载主类 12132
  7. 1
  8. 2
  9. 3
  10. 4
  11. 5
  12. 6

5. jmap:导出内存映像文件&内存使用情况

基本情况

jmap(JVM Memory Map) : 作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。
开发人员可以在控制台中输入命令“ jmap-help ”查阅jmap工具的具体使用方式和一些标准选项配置。
官方帮助文档:
JDK8
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
JDK11
https://docs.oracle.com/en/java/javase/11/tools/jmap.html#GUID-D2340719-82BA-4077-B0F3-2803269B7F41

基本语法

它的基本使用语法为:

  1. jmap [option] <pid>
  2. jmap [option] <executable <core>
  3. jmap [option] [server_id@]<remote server IP or hostname>
  4. 1
  5. 2
  6. 3

其中option包括:

选项 作用
-dump 生成dump文件
-finalizerinfo 以ClassLoader为统计口径输出永久代的内存状态信息
-help 输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
-histo 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
-permstat 以ClassLoader为统计口径输出永久代的内存状态信息
-F 当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件

说明:这些参数和linux下输入显示的命令多少会有不同,包括也受jdk版本的影响。

生成Java堆转储快照:dump文件

特别的:-dumplive 只保存堆中的存活对象

  1. -dump
  2. 1

输出整个堆空间的详细信息

包括GC的使用、堆配置信息,以及内存的使用信息等

  1. -heap
  2. 1

输出堆中对象的统计信息

包括类、实例数量和合计容量
特别的:-histolive 只统计堆中的存活对象

  1. -histo
  2. 1

输出永久代的内存状态信息

以 ClassLoader 为统计口径输出永久代的内存状态信息
仅 linux/solaris 平台有效

  1. -permstat
  2. 1

显示执行finalize方法的对象

显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象
仅 linux/solaris 平台有效

  1. -finalizerinfo
  2. 1

强制执行生成dump文件

当虚拟机进程对 -dump 选项没有任何响应时,可使用此选项强制执行生成dump文件
仅 linux/solaris 平台有效

  1. -F
  2. 1

帮助命令

jmap工具使用的帮助命令

  1. -h | -help
  2. 1

传递参数

传递参数给map启动的ivm

  1. -J <flag>
  2. 1

使用1:导出内存映像文件

一般来说,使用jmap指令生成dump文件的操作算得上是最常用的jmap命令之一,将堆中所有存活对象导出至一个文件之中。
Heap Dump又叫做堆存储文件,指一个Java进程在某个时间点的内存快照。Heap Dump在触发内存快照的时候会保存此刻的信息如下:

  • All Object’s

Class, fields, primitive values and references

  • All Classes

ClassLoader, name, super class, static fields

  • Garbage Collection Roots

Objects defined to be reachable by the JVM

  • Thread Stacks and Local Variables

The call-stacks of threads at the moment of the snapshot, and per-frame information about local objects
说明:
1.通常在写 Heap Dump 文件前会触发一次 Full GC , 所以 heap dump 文件里保存的都是 Full GC 后留下的对象信息。

手动的方式

  1. jmap -dump:format=b,file=<filename.hprof><pid>
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图41

  1. C:\Users\cpucode>jmap -dump:format=b,file=D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jmap\Manual.hprof 19172
  2. Heap dump file created
  3. C:\Users\cpucode>jmap -dump:format=b,file=D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jmap\Manual2.hprof 19172
  4. Heap dump file created
  5. C:\Users\cpucode>jmap -dump:format=b,file=D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jmap\Manual3.hprof 19172
  6. Heap dump file created
  7. 1
  8. 2
  9. 3
  10. 4
  11. 5
  12. 6
  13. 7
  14. 8

快照存活对象

  1. jmap -dump:live,format=b,file=<filename.hprof><pid>
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图42

  1. C:\Users\cpucode>jmap -dump:live,format=b,file=D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jmap\ManualLive.hprof 19172
  2. Heap dump file created
  3. 1
  4. 2

自动的方式

当程序发生OOM退出系统时,一些瞬时信息都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时。
此时若能在OOM时,自动导出dump文件就显得非常迫切。
这里介绍一种比较常用的取得堆快照文件的方法,即使用:
在程序发生OOM时,导出应用程序的当前堆快照 :

  1. -XX:+HeapDumpOnOutOfMemoryError
  2. 1

可以指定堆快照的保存位置

  1. -XX:HeapDumpPath==<filename.hprof>
  2. 1

比如:

  1. -Xmx100m -XX:+HeapDumpOnOutOfMemoryError
  2. -XX:HeapDumpPath=D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jmap\AutoDump.hprof
  3. 1
  4. 2

32,JVM监控及诊断工具-命令行篇 - 图43

使用2:显示堆内存相关信息

查看各区大小

  1. jmap -heap pid
  2. 1

所有类型使用的内存

  1. jmap -histo pid
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图44

  1. C:\Users\cpucode>jmap -histo 12036
  2. num #instances #bytes class name
  3. ----------------------------------------------
  4. 1: 1089 65997504 [B
  5. 2: 208 445520 [I
  6. 3: 4529 442120 [C
  7. 4: 4380 105120 java.lang.String
  8. 5: 697 79680 java.lang.Class
  9. 6: 637 45104 [Ljava.lang.Object;
  10. 7: 791 31640 java.util.TreeMap$Entry
  11. 8: 640 25600 java.util.LinkedHashMap$Entry
  12. 9: 426 18872 [Ljava.lang.String;
  13. 10: 365 11680 java.util.HashMap$Node
  14. 11: 21 8464 [Ljava.util.HashMap$Node;
  15. 12: 109 7848 java.lang.reflect.Field
  16. 13: 16 6016 java.lang.Thread
  17. 14: 91 5824 java.net.URL
  18. 1
  19. 2
  20. 3
  21. 4
  22. 5
  23. 6
  24. 7
  25. 8
  26. 9
  27. 10
  28. 11
  29. 12
  30. 13
  31. 14
  32. 15
  33. 16
  34. 17
  35. 18

使用3:其它作用

查看系统的ClassLoader信息

  1. jmap -permstat pid
  2. 1

查看堆积在finalizer队列中的对象

  1. jmap -finalizerinfo
  2. 1

小结

由于 jmap 将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。
也就是说,由 jmap 导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。
举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么 :live 选项将无法探知到这些对象。
另外,如果某个线程长时间无法跑到安全点, jmap 将一直等下去。
与前面讲的 jstat 则不同 , 垃圾回收器会主动将 jstat 所需要的摘要数据保存至固定位置之中,而 jstat 只需直接读取即可。

6. jhat:JDK自带堆分析工具

基本情况

jhat(JVM Heap Analysis Topl) :
Sun JDK 提供的jhat命令与 jmap 命令搭配使用,用于分析 jmap 生成的 heap dump 文件(堆转储快照)。
jhat 内置了一个微型的 HTTP/HTML 服务器,生成 dump 文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。
使用了 jhat 命令,就启动了一个http服务,端口是7000 , 即 http://localhost:7000/ , 就可以在浏览器里分析。
说明:jhat命令在JDK9、JDK10中已经被删除,官方建议用 VisualVM 代替。

  1. jhat -help
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图45

  1. D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jhat>jhat -help
  2. Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
  3. -J<flag> Pass <flag> directly to the runtime system. For
  4. example, -J-mx512m to use a maximum heap size of 512MB
  5. -stack false: Turn off tracking object allocation call stack.
  6. -refs false: Turn off tracking of references to objects
  7. -port <port>: Set the port for the HTTP server. Defaults to 7000
  8. -exclude <file>: Specify a file that lists data members that should
  9. be excluded from the reachableFrom query.
  10. -baseline <file>: Specify a baseline object dump. Objects in
  11. both heap dumps with the same ID and same class will
  12. be marked as not being "new".
  13. -debug <int>: Set debug level.
  14. 0: No debug output
  15. 1: Debug hprof file parsing
  16. 2: Debug hprof file parsing, no server
  17. -version Report version number
  18. -h|-help Print this help and exit
  19. <file> The file to read
  20. For a dump file that contains multiple heap dumps,
  21. you may specify which dump in the file
  22. by appending "#<number>" to the file name, i.e. "foo.hprof#3".
  23. All boolean options default to "true"
  24. 1
  25. 2
  26. 3
  27. 4
  28. 5
  29. 6
  30. 7
  31. 8
  32. 9
  33. 10
  34. 11
  35. 12
  36. 13
  37. 14
  38. 15
  39. 16
  40. 17
  41. 18
  42. 19
  43. 20
  44. 21
  45. 22
  46. 23
  47. 24
  48. 25
  49. 26
  50. 27

基本语法

指定一个基准堆转储

  1. jhat -baseline exclude-file
  2. 1

设置debug级别

  1. jhat -debug int file
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图46
32,JVM监控及诊断工具-命令行篇 - 图47

  1. d:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jhat>jhat -debug 2 Manual2.hprof
  2. 1

启动后显示版本信息就退出

  1. jhat -version
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图48

  1. D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jhat>jhat -version
  2. jhat version 2.0 (java version 1.8.0_272)
  3. 1
  4. 2

传入启动参数,比如-J-Xmx512m

  1. jhat -J<flag>
  2. 1

关闭|打开对象分配调用栈跟踪

  1. jhat -stack falseltrue
  2. 1

关闭|打开对象引用跟踪

  1. jhat -refs false|true
  2. 1

32,JVM监控及诊断工具-命令行篇 - 图49

  1. D:\Date\github\java\JVM\src\com\cpucode\java\command\tools\jhat>jhat -refs true Manual.hprof
  2. Reading from Manual.hprof...
  3. Dump file created Fri Feb 05 23:16:53 CST 2021
  4. Snapshot read, resolving...
  5. Resolving 23824 objects...
  6. Chasing references, expect 4 dots....
  7. Eliminating duplicate references....
  8. Snapshot resolved.
  9. Started HTTP server on port 7000
  10. Server is ready.
  11. 1
  12. 2
  13. 3
  14. 4
  15. 5
  16. 6
  17. 7
  18. 8
  19. 9
  20. 10

设置jhat HTTP Server的端口号,默认7000

  1. jhat -port port-number
  2. 1

执行对象查询时需要排除的数据成员列表文件

  1. jhat -exclude exclude-file
  2. 1

7. jstack:打印JVM中线程快照

基本情况

jstack(JVM stlack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。
线程快照 : 当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。
这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用 jstack 显示各个线程调用的堆栈情况。
官方帮助文档:
https://docs.oracle.com/en/java/javase/11/tools/jstack.html#GUID-721096FC-237B-473C-A461-DBBBB79E4F6A
在 thread dump 中,要留意下面几种状态

  • 死锁,Deadlock
  • 等待资源,Waiting on condition
  • 等待获取监视器,Waiting on monitor entry
  • 阻塞,Blocked
  • 执行中,Runnable
  • 暂停,Suspended
  • 对象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked

    基本语法

    它的基本使用语法为:

    1. jstack option pid
    2. 1

    帮助 :

    1. C:\Users\cpucode>jstack -help
    2. Usage:
    3. jstack [-l][-e] <pid>
    4. (to connect to running process)
    5. Options:
    6. -l long listing. Prints additional information about locks
    7. -e extended listing. Prints additional information about threads
    8. -? -h --help -help to print this help message
    9. 1
    10. 2
    11. 3
    12. 4
    13. 5
    14. 6
    15. 7
    16. 8
    17. 9

    32,JVM监控及诊断工具-命令行篇 - 图50
    jstack管理远程进程的话,需要在远程程序的启动参数中增加:

  • Djava.rmi.server.hostname=……

  • Dcom.sun.management.jmxremote
  • Dcom.sun.management.jmxremote.port=8888
  • Dcom.sun.management.jmxremote.authenticate=false
  • Dcom.sun.management.jmxremote.ssl=false

    当正常输出的请求不被响应时,强制输出线程堆栈

    1. jstack -F
    2. 1

    打印有关线程的附加信息

    1. jstack -e PID
    2. 1

    32,JVM监控及诊断工具-命令行篇 - 图51

    1. C:\Users\cpucode>jstack -e 21952
    2. 1

    除堆栈外,显示关于锁的附加信息

    1. jstack -l PID
    2. 1

    32,JVM监控及诊断工具-命令行篇 - 图52

    1. C:\Users\cpucode>jstack -l 21952
    2. 1

    如果调用到本地方法的话,可以显示C/C++的堆栈

    1. jstack -m
    2. 1

    帮助操作

    1. jstack -h
    2. 1

    8. jcmd:多功能命令行

    32,JVM监控及诊断工具-命令行篇 - 图53

    基本情况

    在JDK 1.7以后,新增了一个命令行工具 jcmd 。
    它是一个多功能的工具,可以用来实现前面除了 jstat 之外所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。
    jcmd 拥有 jmap 的大部分功能,并且在Oracle的官方网站上也推荐使用 jcmd 命令代 jmap 命令
    官方帮助文档:
    https://docs.oracle.com/en/java/javase/11/tools/jcmd.html#GUID-59153599-875E-447D-8D98-0078A5778F05

    基本语法

    1. C:\Users\cpucode>jcmd -help
    2. 1

    32,JVM监控及诊断工具-命令行篇 - 图54

    列出所有的JVM进程

    1. jcmd -l
    2. 1

    32,JVM监控及诊断工具-命令行篇 - 图55

    1. C:\Users\cpucode>jcmd -l
    2. 4032 org.jetbrains.jps.cmdline.Launcher D:/Program Files/JetBrains/IntelliJ
    3. IDEA 2020.2.3/lib/netty-buffer-4.1.47.Final.jar;D:/Program Files/JetBrains/IntelliJ
    4. IDEA 2020.2.3/lib/log4j.jar;D:/Program Files/JetBrains/IntelliJ
    5. IDEA 2020.2.3/lib/maven-builder-support-3.6.1.jar;D:/Program Files/JetBrains/IntelliJ
    6. IDEA 2020.2.3/lib/jps-model.jar;D:/Program Files/JetBrains/IntelliJ
    7. IDEA 2020.2.3/lib/maven-artifact-3.6.1.jar;D:/Program Files/JetBrains/IntelliJ
    8. IDEA 2020.2.3/lib/gson-2.8.6.jar;D:/Program Files/JetBrains/IntelliJ
    9. IDEA 2020.2.3/lib/nanoxml-2.2.3.jar;D:/Program Files/JetBrains/IntelliJ
    10. IDEA 2020.2.3/lib/plexus-component-annotations-1.7.1.jar;D:/Program Files/JetBrains/IntelliJ
    11. IDEA 2020.2.3/lib/util.jar;D:/Program Files/JetBrains/IntelliJ
    12. IDEA 2020.2.3/lib/commons-lang3-3.9.jar;D:/Program Files/JetBrains/IntelliJ
    13. IDEA 2020.2.3/lib/plexus-utils-3.2.0.jar;D:/Program Files/JetBrains/IntelliJ
    14. IDEA 2020.2.3/lib/maven-repository-metadata-3.6.1.jar;D:/Program Files/JetBrains/IntelliJ
    15. IDEA 2020.2.3/lib/maven-resolver
    16. 16516 com.cpucode.java.command.tools.jstack.ThreadDeadLock
    17. 9604 jdk.jcmd/sun.tools.jcmd.JCmd -l
    18. 11736 c:\Users\cpucode\.vscode\extensions\redhat.java-0.74.0\server\plugins\org.eclipse.equinox.launcher_1.6.0.v20200915-1508.jar
    19. -configuration c:\Users\cpucode\AppData\Roaming\Code\User\globalStorage\redhat.java\0.74.0\config_win
    20. -data c:\Users\cpucode\AppData\Roaming\Code\User\workspaceStorage\3cfbb11b7c66d8952d43190664300d9b\redhat.java\jdt_ws
    21. 1
    22. 2
    23. 3
    24. 4
    25. 5
    26. 6
    27. 7
    28. 8
    29. 9
    30. 10
    31. 11
    32. 12
    33. 13
    34. 14
    35. 15
    36. 16
    37. 17
    38. 18
    39. 19
    40. 20
    41. 21
    42. 22
    43. 23
    44. 24

    针对指定的进程,列出支持的所有命令

    1. jcmd pid help
    2. 1

    32,JVM监控及诊断工具-命令行篇 - 图56

    1. C:\Users\cpucode>jcmd 16516 help
    2. 16516:
    3. The following commands are available:
    4. VM.unlock_commercial_features
    5. JFR.configure
    6. JFR.stop
    7. JFR.start
    8. JFR.dump
    9. JFR.check
    10. VM.native_memory
    11. ManagementAgent.stop
    12. ManagementAgent.start_local
    13. ManagementAgent.start
    14. VM.classloader_stats
    15. GC.rotate_log
    16. Thread.print
    17. GC.class_stats
    18. GC.class_histogram
    19. GC.heap_dump
    20. GC.finalizer_info
    21. GC.heap_info
    22. GC.run_finalization
    23. GC.run
    24. VM.uptime
    25. VM.dynlibs
    26. VM.flags
    27. VM.system_properties
    28. VM.command_line
    29. VM.version
    30. help
    31. For more information about a specific command use 'help <command>'.
    32. 1
    33. 2
    34. 3
    35. 4
    36. 5
    37. 6
    38. 7
    39. 8
    40. 9
    41. 10
    42. 11
    43. 12
    44. 13
    45. 14
    46. 15
    47. 16
    48. 17
    49. 18
    50. 19
    51. 20
    52. 21
    53. 22
    54. 23
    55. 24
    56. 25
    57. 26
    58. 27
    59. 28
    60. 29
    61. 30
    62. 31
    63. 32

    显示指定进程的指令命令的数据

    你可以探索 jcmd 中的下述功能,看看有没有适合你项目的监控项:

  • Compiler.CodeHeap_Analytics

  • Compiler.codecache
  • Compiler.codelist
  • Compiler.directives_add
  • Compiler.directives_clear
  • Compiler.directives_print
  • Compiler.directives_remove
    1. jcmd pid 具体命令
    2. 1
    1. jcmd 16516 VM.version
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图57
    1. jcmd 16516 VM.command_line
    2. 1
    32,JVM监控及诊断工具-命令行篇 - 图58
    1. C:\Users\cpucode>jcmd 16516 VM.flags
    2. 16516:
    3. -XX:CICompilerCount=12 -XX:InitialHeapSize=257949696
    4. -XX:MaxHeapSize=4125097984 -XX:MaxNewSize=1374683136
    5. -XX:MinHeapDeltaBytes=524288 -XX:NewSize=85983232
    6. -XX:OldSize=171966464 -XX:+UseCompressedClassPointers
    7. -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation
    8. -XX:+UseParallelGC
    9. 1
    10. 2
    11. 3
    12. 4
    13. 5
    14. 6
    15. 7
    16. 8
    32,JVM监控及诊断工具-命令行篇 - 图59

    9. jstatd:远程主机信息收集

    之前的指令只涉及到监控本机的Java应用程序,而在这些工具中,一些监控工具也支持对远程计算机的监控(如 jps 、jstat )。为了启用远程监控,则需要配合使用 jstatd 工具。
    命令 jstatd 是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。
    jstatd 服务器将本机的Java应用程序信息传递到远程计算机。
    32,JVM监控及诊断工具-命令行篇 - 图60