JVM性能监控之命令行工具全解

1、概述

性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。

Java作为最流行的编程语言之一,其应用性能诊断一直受到业界的广泛关注,可能造成Java应用出现性能问题的因素非常多,例如线程控制、磁盘读写、数据库访问、网络IO、垃圾收集等。Java性能诊断工具非常多,但是有时候没有工具就得截止Java自带的命令行工具监控,本篇文章我们详解Java自带的所有命令行工具。

所有的命令行工具都在jdk的bin目录下

这些命令行工具的源码是在jdk下的lib目录中的tools.jar中,解压即可看到

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

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

说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。

语法:

$ jps --help
illegal argument: --help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]

选项说明:

  • -q:仅仅显示LVMID(local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等

  • -l:输出应用程序主类的全类名 或 如果进程执行的是jar包,则输出jar完整路径

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

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

说明:以上参数可以综合使用(多个参数一起使用)。

补充:如果某 Java 进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该Java 进程。

实例:

/**
 * @author liuchao
 * @date 2023/3/21
 */
public class Test_01 {

    public static void main(String[] args) {
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}

代码很简单就是让程序无限等待着,然后咱们执行jps加上不同的选项,看看结果如何

# 无选项 可以看出只是展示了Test_01类名称
$ jps
55122
55443 Launcher
55444 Test_01
55481 Jps
55212 RemoteMavenServer36

liuchao at liuchaodeMacBook-Pro-2 in ~
# 加-q选项,可以看出只是展示出了进程id
$ jps -q
55122
55443
55444
55212
55485

liuchao at liuchaodeMacBook-Pro-2 in ~
# 加-l选项,可以看出完整类名
$ jps -l
55488 sun.tools.jps.Jps
55122
55443 org.jetbrains.jps.cmdline.Launcher
55444 com.lc.test.Test_01
55212 org.jetbrains.idea.maven.server.RemoteMavenServer36

liuchao at liuchaodeMacBook-Pro-2 in ~
# 加-m选项,针对 jps命令,可以看出我们给传入的参数 -m
$ jps -m
55490 Jps -m
55122
55443 Launcher /Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-builders.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-builders-6.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-javac-extension.jar:/Applications/IntelliJ IDEA.app/Contents/lib/util.jar:/Applications/IntelliJ IDEA.app/Contents/lib/util_rt.jar:/Applications/IntelliJ IDEA.app/Contents/lib/annotations.jar:/Applications/IntelliJ IDEA.app/Contents/lib/3rd-party-rt.jar:/Applications/IntelliJ IDEA.app/Contents/lib/protobuf.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jps-model.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/javac2.jar:/Applications/IntelliJ IDEA.app/Contents/lib/forms_rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/aether-dependency-resolver.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/JavaEE/lib/jasper-v2-rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/Kotli
55444 Test_01
55212 RemoteMavenServer36

liuchao at liuchaodeMacBook-Pro-2 in ~
# 加-v选项,可以列出JVM启动时的参数,想看线上环境启动参数可以使用此命令
$ jps -v
55122  -Xms128m -Xmx750m -XX:ReservedCodeCacheSize=512m -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=50 -XX:CICompilerCount=2 -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -XX:+IgnoreUnrecognizedVMOptions -XX:CompileCommand=exclude,com/intellij/openapi/vfs/impl/FilePartNodeRoot,trieDescend -ea -Dsun.io.useCanonCaches=false -Dsun.java2d.metal=true -Dsun.java2d.metal.displaySync=false -Djbr.catch.SIGABRT=true -Djdk.http.auth.tunneling.disabledSchemes="" -Djdk.attach.allowAttachSelf=true -Djdk.module.illegalAccess.silent=true -Dkotlinx.coroutines.debug=off -XX:ErrorFile=/Users/liuchao/java_error_in_idea_%p.log -XX:HeapDumpPath=/Users/liuchao/java_error_in_idea.hprof -javaagent:/Applications/IntelliJ IDEA.app/Contents/plugins/ja-netfilter/ja-netfilter.jar --add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED -Xmx2048m -Djb.vmOptionsFile=/Users/liuchao/Library/Application Support/JetBrains/IntelliJIdea2022.3/idea.vmoptions --add
55443 Launcher -Xmx700m -Djava.awt.headless=true -Djna.boot.library.path=/Applications/IntelliJ IDEA.app/Contents/lib/jna/amd64 -Djna.nosys=true -Djna.noclasspath=true --add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -Dpreload.project.path=/Users/liuchao/java/tool/idea/2022/test_01 -Dpreload.config.path=/Users/liuchao/Library/Application Support/JetBrains/IntelliJIdea2022.3/options -Dexternal.pro
55492 Jps -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_351.jdk/Contents/Home -Xms8m
55444 Test_01 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=55492:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
55212 RemoteMavenServer36 -Djava.awt.headless=true -Dmaven.defaultProjectBuilder.disableGlobalModelCache=true -Didea.version=2022.3.2 -Didea.maven.embedder.version=3.8.6 -Xmx768m -Dmaven.ext.class.path=/Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven-event-listener.jar -Dfile.encoding=UTF-8

liuchao at liuchaodeMacBook-Pro-2 in ~
# 多选项组合使用
$ jps -ml
55122
55443 org.jetbrains.jps.cmdline.Launcher /Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-builders.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-builders-6.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-javac-extension.jar:/Applications/IntelliJ IDEA.app/Contents/lib/util.jar:/Applications/IntelliJ IDEA.app/Contents/lib/util_rt.jar:/Applications/IntelliJ IDEA.app/Contents/lib/annotations.jar:/Applications/IntelliJ IDEA.app/Contents/lib/3rd-party-rt.jar:/Applications/IntelliJ IDEA.app/Contents/lib/protobuf.jar:/Applications/IntelliJ IDEA.app/Contents/lib/jps-model.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/javac2.jar:/Applications/IntelliJ IDEA.app/Contents/lib/forms_rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/aether-dependency-resolver.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/JavaEE/lib/jasper-v2-rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/Kotli
55444 Test_01
55494 sun.tools.jps.Jps -ml
55212 org.jetbrains.idea.maven.server.RemoteMavenServer36

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

语法:

$ jstat --help
invalid argument count
Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
  <option>      An option reported by the -options option
  <vmid>        Java进程ID,通过JPS可以看到. 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.
  -h            输出多少行以后再次输出头信息(表头).
  <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>       监控几次,用于查询的总次数.
  -J<flag>      Pass <flag> directly to the runtime system.
  -t            用于在输出信息前面加一个Timestamp列,线程进程自启动以后运行的总时间,单位:秒

option参数

选项option可以由以下值构成。

类装载相关的:

  • -class:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等

垃圾回收相关的:

  • -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。

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

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

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

  • -gcnew:显示新生代GC状况

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

  • -geold:显示老年代GC状况

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

  • -gcpermcapacity:显示永久代使用到的最大、最小空间。

JIT相关的:

  • -compiler:显示JIT编译器编译过的方法、耗时等信息

  • -printcompilation:输出已经被JIT编译的方法

要查询有哪些options通过 “ jstat -options” 查看

实例:

liuchao at liuchaodeMacBook-Pro-2 in ~
$ jps
55122
56057 Jps
56043 Launcher
56044 Test_01
55212 RemoteMavenServer36
# 这里我们还是以 Test_01 为例,进程ID是56044
$ jstat -class 56044
# 加载类个数    加载类占用字节数   卸载类个数  卸载类占用字节数  使用时间
Loaded  Bytes  Unloaded  Bytes     Time
   540  1087.3        0     0.0       0.10

$ jstat -compiler 56044
# 编译类个数  失败个数  无效类个数  用时   失败类型  失败方法
Compiled Failed Invalid   Time   FailedType FailedMethod
      26      0       0     0.01          0
$ jstat -printcompilation 56044
Compiled  Size  Type Method
      26      1    1 java/lang/Object <init>

$ jstat -gc 56044
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000

# 查看5次,间隔1s
$ jstat -gc 56044  1s 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000

$ jstat -gccapacity 56044  1s 5
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
 87040.0 1397760.0  87040.0 10752.0 10752.0  65536.0   175104.0  2796544.0   175104.0   175104.0      0.0 1056768.0   4480.0      0.0 1048576.0    384.0      0     0
 87040.0 1397760.0  87040.0 10752.0 10752.0  65536.0   175104.0  2796544.0   175104.0   175104.0      0.0 1056768.0   4480.0      0.0 1048576.0    384.0      0     0
 87040.0 1397760.0  87040.0 10752.0 10752.0  65536.0   175104.0  2796544.0   175104.0   175104.0      0.0 1056768.0   4480.0      0.0 1048576.0    384.0      0     0
 87040.0 1397760.0  87040.0 10752.0 10752.0  65536.0   175104.0  2796544.0   175104.0   175104.0      0.0 1056768.0   4480.0      0.0 1048576.0    384.0      0     0
 87040.0 1397760.0  87040.0 10752.0 10752.0  65536.0   175104.0  2796544.0   175104.0   175104.0      0.0 1056768.0   4480.0      0.0 1048576.0    384.0      0     0

$ jstat -gcutil 56044  1s 5
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000

$ jstat -gccause 56044  1s 5
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000 No GC                No GC
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000 No GC                No GC
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000 No GC                No GC
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000 No GC                No GC
  0.00   0.00   6.00   0.00  17.41  19.80      0    0.000     0    0.000    0.000 No GC                No GC

$ jstat -gcnew 56044  1s 5
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
10752.0 10752.0    0.0    0.0 15  15    0.0  65536.0   3932.2      0    0.000
10752.0 10752.0    0.0    0.0 15  15    0.0  65536.0   3932.2      0    0.000
10752.0 10752.0    0.0    0.0 15  15    0.0  65536.0   3932.2      0    0.000
10752.0 10752.0    0.0    0.0 15  15    0.0  65536.0   3932.2      0    0.000
10752.0 10752.0    0.0    0.0 15  15    0.0  65536.0   3932.2      0    0.000

$ jstat -gcnewcapacity 56044  1s 5
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
   87040.0  1397760.0    87040.0 465920.0  10752.0 465920.0  10752.0  1396736.0    65536.0     0     0
   87040.0  1397760.0    87040.0 465920.0  10752.0 465920.0  10752.0  1396736.0    65536.0     0     0
   87040.0  1397760.0    87040.0 465920.0  10752.0 465920.0  10752.0  1396736.0    65536.0     0     0
   87040.0  1397760.0    87040.0 465920.0  10752.0 465920.0  10752.0  1396736.0    65536.0     0     0
   87040.0  1397760.0    87040.0 465920.0  10752.0 465920.0  10752.0  1396736.0    65536.0     0     0

$ jstat -gcold  56044  1s 5
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
  4480.0    779.8    384.0     76.0    175104.0         0.0      0     0    0.000    0.000
  4480.0    779.8    384.0     76.0    175104.0         0.0      0     0    0.000    0.000
  4480.0    779.8    384.0     76.0    175104.0         0.0      0     0    0.000    0.000
  4480.0    779.8    384.0     76.0    175104.0         0.0      0     0    0.000    0.000
  4480.0    779.8    384.0     76.0    175104.0         0.0      0     0    0.000    0.000

$ jstat -gcoldcapacity  56044  1s 5
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
   175104.0   2796544.0    175104.0    175104.0     0     0    0.000    0.000
   175104.0   2796544.0    175104.0    175104.0     0     0    0.000    0.000
   175104.0   2796544.0    175104.0    175104.0     0     0    0.000    0.000
   175104.0   2796544.0    175104.0    175104.0     0     0    0.000    0.000
   175104.0   2796544.0    175104.0    175104.0     0     0    0.000    0.000

$ jstat -gc -t  56044  1s 5
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1336.3 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1337.3 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1338.4 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1339.3 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1340.4 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000

$ jstat -gc -t -h2  56044  1s 5
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1373.0 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1374.0 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1375.0 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
         1376.0 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1377.0 10752.0 10752.0  0.0    0.0   65536.0   3932.2   175104.0     0.0     4480.0 779.8  384.0   76.0       0    0.000   0      0.000    0.000

这里详细解释每列的意思

表头

含义(字节)

EC

Eden区的大小

EU

Eden区已使用的大小

S0C

幸存者0区的大小

S1C

幸存者1区的大小

S0U

幸存者0区已使用的大小

S1U

幸存者1区已使用的大小

MC

元空间的大小

MU

元空间已使用的大小

OC

老年代的大小

OU

老年代已使用的大小

CCSC

压缩类空间的大小

CCSU

压缩类空间已使用的大小

YGC

从应用程序启动到采样时young gc的次数

YGCT

从应用程序启动到采样时young gc消耗时间(秒)

FGC

从应用程序启动到采样时full gc的次数

FGCT

从应用程序启动到采样时的full gc的消耗时间(秒)

GCT

从应用程序启动到采样时gc的总时间

补充: jstat还可以用来判断是否出现内存泄漏。

第1步:在长时间运行的 Java 程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中 OU 列(即已占用的老年代内存)的最小值。

第2步:然后,我们每隔一段较长的时间重复一次上述操作,来获得多组 OU 最小值。如果这些值呈上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。

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

jinfo(Configuration Info for Java):查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。

基本使用语法为:jinfo [options] pid

说明:java 进程ID必须要加上

选项

选项说明

no option

输出全部的参数和系统属性

-flag name

输出对应名称的参数

-flag [+-]name

开启或者关闭对应名称的参数 只有被标记为manageable的参数才可以被动态修改

-flag name=value

设定对应名称的参数

-flags

输出全部的参数

-sysprops

输出系统属性

实例:

  • jinfo ID

# 输出全部的参数和系统属性
[root@liuchao app]# jinfo 23025
Attaching to process ID 23025, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.221-b11
Java System Properties:
  • jinfo sysprops ID

[root@liuchao app]# jinfo -sysprops 23025
Attaching to process ID 23025, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.221-b11
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.221-b11
sun.boot.library.path = /usr/java/jdk1.8.0_221-amd64/jre/lib/amd64
java.protocol.handler.pkgs = org.springframework.boot.loader
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
  • jinfo -flags ID

[root@liuchao app]# jinfo -flags 23025
Attaching to process ID 23025, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.221-b11
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=1052770304 -XX:MaxHeapSize=16812867584 -XX:MaxNewSize=5604114432 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=350748672 -XX:OldSize=702021632 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
Command line:
  • jinfo -flag ID

[root@liuchao app]# jinfo -flag UseParallelGC 23025
-XX:+UseParallelGC
[root@liuchao app]# jinfo -flag UseG1GC 23025
-XX:-UseG1GC
[root@liuchao app]#
  • jinfo -flag [+-]name ID

[root@liuchao app]# jinfo -flag PrintGCDetails 23025
-XX:-PrintGCDetails
[root@liuchao app]#
[root@liuchao app]# jinfo -flag +PrintGCDetails 23025
[root@liuchao app]#
[root@liuchao app]# jinfo -flag PrintGCDetails 23025
-XX:+PrintGCDetails
[root@liuchao app]#
[root@liuchao app]#
[root@liuchao app]# jinfo -flag -PrintGCDetails 23025
[root@liuchao app]#
[root@liuchao app]#
[root@liuchao app]# jinfo -flag PrintGCDetails 23025
-XX:-PrintGCDetails
[root@liuchao app]#

拓展:

  • java -XX:+PrintFlagsInitial 查看所有JVM参数启动的初始值

[Global flags]
     intx ActiveProcessorCount                      = -1                                  {product}
    uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
    uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
    uintx AdaptiveSizePausePolicy                   = 0                                   {product}
...
  • java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值

[Global flags]
     intx ActiveProcessorCount                      = -1                                  {product}
...
     intx CICompilerCount                          := 4                                   {product}
    uintx InitialHeapSize                          := 333447168                           {product}
    uintx MaxHeapSize                              := 1029701632                          {product}
    uintx MaxNewSize                               := 1774714880                          {product}
  • java -XX:+PrintCommandLineFlags 查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值

-XX:InitialHeapSize=332790016 -XX:MaxHeapSize=5324640256 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

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

jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。

官方帮助文档:https://docs.oracle.com/en/java/javase/11/tools/jmap.html

基本使用语法为:

  • jmap [option] <pid>

  • jmap [option] <executable <core>

  • jmap [option] [server_id@] <remote server IP or hostname>

选项

作用

-dump

生成dump文件(Java堆转储快照),-dump:live只保存堆中的存活对象

-heap

输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等

-histo

输出堆空间中对象的统计信息,包括类、实例数量和合计容量,-histo:live只统计堆中的存活对象

-J <flag>

传递参数给jmap启动的jvm

-finalizerinfo

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

-permstat

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

-F

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

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

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

由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。

举个例子,假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。

另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,而jstat只需直接读取即可。

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

jhat(JVM Heap Analysis Tool):Sun JDK提供的jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。

使用了jhat命令,就启动了一个http服务,端口是7000,即http://localhost:7000/,就可以在浏览器里分析。

说明:jhat命令在JDK9、JDK10中已经被删除,官方建议用VisualVM代替。

基本适用语法:jhat <option> <dumpfile>

option参数

作用

-stack false|true

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

-refs false|true

关闭|打开对象引用跟踪

-port port-number

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

-exclude exclude-file

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

-baseline exclude-file

指定一个基准堆转储

-debug int

设置debug级别

-version

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

-J <flag>

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

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

jstack(JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。

生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

官方帮助文档:https://docs.oracle.com/en/java/javase/11/tools/jstack.html

在thread dump中,要留意下面几种状态

  • 死锁,Deadlock(重点关注)

  • 等待资源,Waiting on condition(重点关注)

  • 等待获取监视器,Waiting on monitor entry(重点关注)

  • 阻塞,Blocked(重点关注)

  • 执行中,Runnable

  • 暂停,Suspended

  • 对象等待中,Object.wait() 或 TIMED_WAITING

  • 停止,Parked

option参数

作用

-F

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

-l

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

-m

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

8、jcmd:多功能命令行

在JDK 1.7以后,新增了一个命令行工具jcmd。它是一个多功能的工具,可以用来实现前面除了jstat之外所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。

官方帮助文档:https://docs.oracle.com/en/java/javase/11/tools/jcmd.html

jcmd拥有jmap的大部分功能,并且在Oracle的官方网站上也推荐使用jcmd命令代jmap命令

jcmd -l:列出所有的JVM进程

jcmd 进程号 help:针对指定的进程,列出支持的所有具体命令

[root@liuchao app]# jcmd 23025 help
23025:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.
[root@liuchao app]#

jcmd 进程号 具体命令:显示指定进程的指令命令的数据

  • Thread.print 可以替换 jstack指令

  • GC.class_histogram 可以替换 jmap中的-histo操作

  • GC.heap_dump 可以替换 jmap中的-dump操作

  • GC.run 可以查看GC的执行情况

  • VM.uptime 可以查看程序的总执行时间,可以替换jstat指令中的-t操作

  • VM.system_properties 可以替换 jinfo -sysprops 进程id

  • VM.flags 可以获取JVM的配置参数信息

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

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

猜你喜欢

转载自blog.csdn.net/u011837804/article/details/129717901