• Jcmd 虚拟机诊断利器


    Jcmd 虚拟机诊断利器

    Java虚拟机(JVM)是运行Java程序的抽象化的计算器。今天,来学习下如何轻松诊断正在运行的JVM。

    JDK本身中提供了许多可用的工具,可以用于各种开发、监视和故障排除活动。推荐使用jcmd,简单易懂,可以提供关于JVM运行的各种信息。此外,jcmd是JDK7以后的一个推荐工具,用于增强JVM诊断,性能开销低。

    是什么

    JVMCommand 简称jcmd, 是JDK自带的一个向JVM发送诊断命令请求的小工具,免费使用,位于${JAVA_HOME}/bin目录下。但是,它必须在运行JVM的同一台机器上使用。不能向其它工具提供远程诊断的功能,如 Jconsole。接下来看看如何在诊断JVM。

    获取PID

    在排查问题时,通常情况下,开发者/运维人员需要知道Java程序对用的PID,然后分析PID占用的资源情况。如IO、内存、CPU、线程状态等等。但是前提是:找到PID。JDK 或 linux系统提供了很多种方式给开发者排查正在运行的JVM(PID)

    • jps - Java Virtual Machine Process Status Tool, 访问主机JAVA进程的工具

      AndydeMacBook-Pro:bin andy$ jps
      82800 Jps
      80180 Launcher
      
      • 1
      • 2
      • 3

      jps 命令不带参数时,只显示PID、主类名

      # 只显示pid
      jps -q
      # 显示pid、类名及相关参数
      jps -m
      # 显示pid、运行参数
      jps -v
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • ps - 是linux提供的一个强大的工具,一般根据关键字进行过滤

      ps -ef | grep java
      
      • 1

      在这里插入图片描述

      以上的信息太过复杂,使用awk工具做筛选过滤

      ps -ef | grep java |  awk '{print $2}'
      
      • 1
    • jcmd - 哈哈 今日主角登场,使用该命令,列出所有正在运行的JVM进程

      在这里插入图片描述

      类似 jps -m 命令的效果

    获取进程参数选项

    可以使用jcmd pid help 命令获取指定PID的参数选项列表,不同版本的JVM结果列表略有不同

    AndydeMacBook-Pro:bin andy$ jcmd 80180 help
    80180:
    The following commands are available:
    Compiler.CodeHeap_Analytics
    Compiler.codecache
    Compiler.codelist
    Compiler.directives_add
    Compiler.directives_clear
    Compiler.directives_print
    Compiler.directives_remove
    Compiler.queue
    GC.class_histogram
    GC.finalizer_info
    GC.heap_dump
    GC.heap_info
    GC.run
    GC.run_finalization
    JFR.check
    JFR.configure
    JFR.dump
    JFR.start
    JFR.stop
    JVMTI.agent_load
    JVMTI.data_dump
    ManagementAgent.start
    ManagementAgent.start_local
    ManagementAgent.status
    ManagementAgent.stop
    Thread.print
    VM.cds
    VM.class_hierarchy
    VM.classloader_stats
    VM.classloaders
    VM.command_line
    VM.dynlibs
    VM.events
    VM.flags
    VM.info
    VM.log
    VM.metaspace
    VM.native_memory
    VM.print_touched_methods
    VM.set_flag
    VM.stringtable
    VM.symboltable
    VM.system_properties
    VM.systemdictionary
    VM.uptime
    VM.version
    help
    
    • 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
    • 48
    • 49
    • 50

    jcmd 常用选项

    上述罗列的参数选项非常的多,不做一一介绍。来学习下工作中经常使用的参数选项。

    VM.version

    AndydeMacBook-Pro:bin andy$ jcmd 80180 VM.version
    80180:
    Java HotSpot(TM) 64-Bit Server VM version 17.0.5+9-LTS-191
    JDK 17.0.5
    
    • 1
    • 2
    • 3
    • 4

    获取JVM的基本信息

    VM.system_properties

    获取JVM运行的系统参数,由于篇幅过长,做了一些删减

    AndydeMacBook-Pro:bin andy$ jcmd 80180 VM.system_properties
    80180:
    #Tue Dec 06 10:36:15 CST 2022
    http.proxyHost=127.0.0.1
    java.specification.version=17
    sun.jnu.encoding=UTF-8
    java.class.path=/Applications/IntelliJ IDEA CE.app/Contents/plugins/java/lib/jps-launcher.jar
    https.proxyPort=50154
    java.vm.vendor=Oracle Corporation
    jdt.compiler.useSingleThread=true
    sun.arch.data.model=64
    kotlin.incremental.compilation=true
    kotlin.daemon.client.alive.path="/var/folders/z8/4hs2q4zx73q6zfg2myh6m_kh0000gn/T/kotlin-idea-7350919135759315545-is-running"
    java.vendor.url=https\://java.oracle.com/
    user.timezone=Asia/Shanghai
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    VM.flags

    输出所有使用的VM参数,这些参数要么由开发指定,要么由JVM默认使用:

    AndydeMacBook-Pro:bin andy$ jcmd 80180 VM.flags
    80180:
    -XX:CICompilerCount=4 -XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 -XX:G1EagerReclaimRemSetThreshold=8 -XX:G1HeapRegionSize=1048576 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=134217728 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=440401920 -XX:MinHeapDeltaBytes=1048576 -XX:MinHeapSize=8388608 -XX:NonNMethodCodeHeapSize=5839372 -XX:NonProfiledCodeHeapSize=122909434 -XX:ProfiledCodeHeapSize=122909434 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:SoftMaxHeapSize=734003200 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:-UseNUMA -XX:-UseNUMAInterleaving 
    
    • 1
    • 2
    • 3

    类似的,其他命令(VM.command_line, VM.uptime, VM.dynlibs) 也提供了其他一些非常有用的属性和基本信息,不做一一演示了。

    Thread.print

    之前介绍的指令都是介绍JVM的各种基本参数。现在来看一下跟线程相关的指令,这对JVM故障排除非常有帮助。Thread.print命令用于打印所有运行线程的堆栈信息,获取线程状态。

    AndydeMacBook-Pro:bin andy$ jcmd 80180 Thread.print
    80180:
    2022-12-07 06:45:22
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.0.5+9-LTS-191 mixed mode, sharing):
    
    Threads class SMR info:
    _java_thread_list=0x00007fa2446ab370, length=13, elements={
    0x00007fa244818000, 0x00007fa24481a800, 0x00007fa245092e00, 0x00007fa245812600,
    0x00007fa24580ec00, 0x00007fa245811200, 0x00007fa245811800, 0x00007fa245811e00,
    0x00007fa244819200, 0x00007fa24501d800, 0x00007fa245813400, 0x00007fa244803800,
    0x00007fa2458d7e00
    }
    
    "Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.96ms elapsed=10406.56s tid=0x00007fa244818000 nid=0x4203 waiting on condition  [0x00007000076ef000]
       java.lang.Thread.State: RUNNABLE
    	at java.lang.ref.Reference.waitForReferencePendingList(java.base@17.0.5/Native Method)
    	at java.lang.ref.Reference.processPendingReferences(java.base@17.0.5/Reference.java:253)
    	at java.lang.ref.Reference$ReferenceHandler.run(java.base@17.0.5/Reference.java:215)
    
    "Finalizer" #3 daemon prio=8 os_prio=31 cpu=0.51ms elapsed=10406.56s tid=0x00007fa24481a800 nid=0x4503 in Object.wait()  [0x00007000077f2000]
       java.lang.Thread.State: WAITING (on object monitor)
     ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    GC.class_histogram

    该参数输出JVM 堆使用情况的相关信息。需要注意的是,她将列出所有实例的信息(包含外部类或应用程序类)

    AndydeMacBook-Pro:bin andy$ jcmd 80180 GC.class_histogram
    80180:
     num     #instances         #bytes  class name (module)
    -------------------------------------------------------
       1:         25312        4789808  [B (java.base@17.0.5)
       2:         24623         590952  java.lang.String (java.base@17.0.5)
       3:          1676         531360  [I (java.base@17.0.5)
       4:          4206         508080  java.lang.Class (java.base@17.0.5)
       5:         11604         371328  java.util.concurrent.ConcurrentHashMap$Node (java.base@17.0.5)
       6:          3726         356904  [Ljava.lang.Object; (java.base@17.0.5)
       7:          5806         185792  java.util.HashMap$Node (java.base@17.0.5)
       8:          6847         109552  java.lang.Object (java.base@17.0.5)
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    GC.heap_dump

    故障排查时,通常需要将堆栈信息导出为dump文件,以便开发人员做事后问题分析、定位。跟jmap dump -pid 一样 GC.heap_dump 命令可以导出dump文件

    AndydeMacBook-Pro:Downloads andy$ jcmd 80180 GC.heap_dump ./demo_heap_dump
    80180:
    Dumping heap to ./demo_heap_dump ...
    Heap dump file created [15855508 bytes in 0.246 secs]
    
    • 1
    • 2
    • 3
    • 4

    JFR

    Jcmd 使用JFR来分析应用程序性能。JFR(或Java Flight Recorder)是一个内置于JDK中的评测和事件收集框架。JFR允许我们收集有关JVM和Java应用程序行为的详细低级信息。

    AndydeMacBook-Pro:Downloads andy$ jcmd 80180 JFR.start name=demo_recording settings=profile delay=10s duration=20s filename=./demorecording.jfr
    80180:
    Recording 1 scheduled to start in 10 s. The result will be written to:
    
    /Users/andy/Library/Caches/JetBrains/IdeaIC2022.2/compile-server/demorecording.jfr
    
    • 1
    • 2
    • 3
    • 4
    • 5

    VM.native_memory

    该选项可以提供关于JVM上的堆和非堆内存的许多有用细节信息。因此,对于可以用于调整内存使用情况并检测任何内存泄漏。JVM内存可粗略的分为堆内存和非堆内存。该命令可以获得完整JVM内存使用情况的详细信息。此外,这在定义基于容器的应用程序的内存大小时非常有用。

    AndydeMacBook-Pro:Downloads andy$ jcmd 80180 VM.native_memory
    80180:
    Native Memory Tracking:
    
    Total: reserved=1159598KB, committed=657786KB
    -                 Java Heap (reserved=524288KB, committed=524288KB)
                                (mmap: reserved=524288KB, committed=524288KB) 
     
    -                     Class (reserved=279652KB, committed=29460KB)
                                (classes #6425)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    内存泄露检测

    特定情况下,需要识别JVM中是否存在内存泄露。首先需要定义一个时间基线,然后监控一段时间,以了解内存是否持续增加。因此内存泄露检测需要分两部

    AndydeMacBook-Pro:Downloads andy$ jcmd 80180 VM.native_memory baseline
    80180:
    Baseline succeeded
    
    • 1
    • 2
    • 3
    AndydeMacBook-Pro:Downloads andy$ jcmd 80180 VM.native_memory summary.diff
    80180:
    Native Memory Tracking:
    
    Total: reserved=1162150KB +2540KB, committed=660930KB +3068KB
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    MySQL尾部空格处理与哪些设置有关? 字符集PAD SPACE与NO PAD属性的区别、MySQL字段尾部有空格为什么也能查询出来?
    【模型训练】YOLOv7车辆和行人检测
    基于Python通信程序的设计与实现
    WPF DataGrid详细列表手动显示与隐藏
    vue 项目在加载完成之前,显示预置加载动画
    JDBC的工作原理
    01.02 环境搭建详细介绍
    淘宝/天猫获取淘宝直播分类id接口 API 返回值说明
    [Linux]文件基础-如何管理文件
    【网络编程】基础知识
  • 原文地址:https://blog.csdn.net/u013433591/article/details/128213672