bigywater.tech
Java · 344

jcmd:统一触发 JVM 诊断动作

jcmd 是一个入口,背后是 JVM 的诊断命令。这篇把 JDK 21 上它支持的命令分类数一遍,再把最常用的几类各跑一次,看输出和限制。

49
JDK 21.0.12 这个 JVM 上 jcmd help 列出的命令数
13
VM.flags -all 里 {manageable} 参数的个数(只有这些能 VM.set_flag)
+102400KB
分配 100 MB 直接内存后 NMT summary.diff 的 Other 增量

列出 JVM 与命令

实测 · 本机执行输出
  jcmd 的输出(只列出本实验相关的行):
    <pid> Main
    <pid> jdk.jcmd/sun.tools.jcmd.JCmd
  jcmd <pid> help 列出 49 个命令;按前缀统计: {'Compiler': 8, 'GC': 6, 'JFR': 6, 'JVMTI': 2, 'ManagementAgent': 4, 'Thread': 2, 'VM': 20, 'help': 1}
  全部命令名: 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 JFR.view JVMTI.agent_load JVMTI.data_dump ManagementAgent.start ManagementAgent.start_local ManagementAgent.status ManagementAgent.stop Thread.dump_to_file Thread.print VM.cds VM.class_hierarchy VM.classes VM.classloader_stats VM.classloaders VM.command_line VM.dynlibs VM.events VM.flags VM.info VM.log VM.metaspace VM.native_memory VM.set_flag VM.stringtable VM.symboltable VM.system_properties VM.systemdictionary VM.uptime VM.version help
  jcmd <pid> help Thread.print:
    5510:
    Thread.print
    Print all threads with stacktraces.
    
    Impact: Medium: Depends on the number of threads.
    
    Syntax : Thread.print [options]
    
    Options: (options must be specified using the <key> or <key>=<value> syntax)
    	-l : [optional] print java.util.concurrent locks (BOOLEAN, false)
    	-e : [optional] print extended thread information (BOOLEAN, false)

只读信息命令

实测 · 本机执行输出
  jcmd <pid> VM.version:
    5510:
    OpenJDK 64-Bit Server VM version 21.0.12.1
    JDK 21.0.12.1
  jcmd <pid> VM.uptime:
    5510:
    0.535 s
  jcmd <pid> VM.command_line:
    5510:
    VM Arguments:
    jvm_args: -Xmx256m -XX:+UseG1GC -Dapp.name=demo 
    java_command: Main
    java_class_path (initial): out
    Launcher Type: SUN_STANDARD
  jcmd <pid> GC.heap_info:
    5510:
     garbage-first heap   total 262144K, used 3022K [0x000000012c000000, 0x000000013c000000)
      region size 1024K, 2 young (2048K), 0 survivors (0K)
     Metaspace       used 411K, committed 576K, reserved 1114112K
      class space    used 27K, committed 128K, reserved 1048576K
  jcmd <pid> VM.flags(节选;共 24 个 -XX 参数):
    -XX:ConcGCThreads=2 -XX:G1RemSetHowlMaxNumBuckets=8 -XX:GCDrainStackTargetSize=64 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=160432128 -XX:SoftMaxHeapSize=268435456 -XX:+UseG1GC
  jcmd <pid> VM.system_properties:53 个属性;其中 app.name = demo

VM.set_flag

实测 · 本机执行输出
  jcmd <pid> VM.flags -all | grep manageable:
    共 13 个 manageable 参数;前几个:
       uintx G1PeriodicGCInterval = 0 {manageable} {default}
       double G1PeriodicGCSystemLoadThreshold = 0.000000 {manageable} {default}
       bool HeapDumpAfterFullGC = false {manageable} {default}
       bool HeapDumpBeforeFullGC = false {manageable} {default}
       intx HeapDumpGzipLevel = 0 {manageable} {default}
  尝试改 MaxHeapSize(不是 manageable):
    5510:
    only 'writeable' flags can be set
  改 MinHeapFreeRatio(manageable)前后:
    前:  uintx MinHeapFreeRatio = 40 {manageable} {default}
    set_flag 返回: '5510:\nCommand executed successfully'
    后:  uintx MinHeapFreeRatio = 55 {manageable} {management}
  改一个根本不存在的参数:
    5510:
    flag NoSuchFlag does not exist

GC 与编译器命令

实测 · 本机执行输出
   OK garbage
  制造垃圾后:堆 used 32 MB / total 256 MB
  GC.run 返回: '5510:\nCommand executed successfully'
  GC.run 之后:堆 used 1 MB / total 14 MB
   OK heap
  GC.class_histogram 前 4 行(保留了 50 个 1 MB 数组):
    5510:
     num     #instances         #bytes  class name (module)
    -------------------------------------------------------
       1:         12956       53124120  [B (java.base@21.0.12.1)
  Compiler.codecache:
    5510:
    CodeHeap 'non-profiled nmethods': size=120032Kb used=88Kb max_used=89Kb free=119943Kb
     bounds [0x00000001240cc000, 0x000000012433c000, 0x000000012b604000]
    CodeHeap 'profiled nmethods': size=120016Kb used=358Kb max_used=384Kb free=119658Kb

原生内存 NMT

实测 · 本机执行输出
  没开 NativeMemoryTracking:
    5546:
    Native memory tracking is not enabled
  jcmd <pid> VM.native_memory baseline: '5559:\nBaseline taken'
   OK direct (分配并写满 100 MB 直接内存)
  summary.diff 的 Total 行:
    Total: reserved=1848806KB +102415KB, committed=483526KB +102479KB
  summary.diff 里 Other 一段:
    Other (reserved=102400KB +102400KB, committed=102400KB +102400KB)
                                (malloc=102400KB +102400KB #1 +1)

JFR

实测 · 本机执行输出
  JFR.start: Use jcmd 5575 JFR.dump name=r1 filename=FILEPATH to copy recording data to file.
   149999997 OK work | OK garbage
  JFR.check:
    5575:
    Recording 1: name=r1 maxsize=250.0MB (running)
  JFR.dump: <实验目录> ;文件大小 408 KB
  JFR.stop: 5575:
Stopped recording "r1".
  jfr summary 里几个事件的计数:
     jdk.ObjectAllocationSample 131 1769
     jdk.GCPhasePause 11 261
     jdk.GarbageCollection 10 201
     jdk.ExecutionSample 4 40
     jdk.CPULoad 0 0

分步演示

jcmd
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,G1,-Xmx256m;所有命令都是命令行里真实运行的 jcmd
    • 没有验证:GC.heap_dump 的耗时与文件大小(见另一篇 jmap)、Compiler.directives_* 与 JVMTI.agent_load 的实际效果、ManagementAgent.* 启动远程 JMX、在 JDK 17 / 27 上命令集的差别、jcmd 对容器内 JVM 的 attach 限制(这台没有 Docker)
    京ICP备2026067502号-1京公网安备11010502063487号