bigywater.tech
Java · 206

JMX:把 JVM 指标变成可管理的 MBean

JMX 怎么把 JVM 的指标和自己的组件变成可管理的 MBean?这篇用平台 MBean、自己写的 MBean、通知和一个真实的远程连接逐项验证(JFR 在前一篇,NMT 在后面)。

27 个
平台 MBeanServer 里的 MBean 总数
RuntimeMBeanException
MBean 方法内抛异常到调用方时的类型
146.69 µs
远程(RMI,回环)getAttribute 一次的平均耗时

平台 MBean

实测 · 本机执行输出
  平台 MBeanServer 的域:[JMImplementation, com.sun.management, java.lang, java.nio, java.util.logging, jdk.management.jfr];MBean 总数 = 27
  java.lang 域里的 MBean 类型:[ClassLoading, Compilation, GarbageCollector, Memory, MemoryManager, MemoryPool, OperatingSystem, Runtime, Threading]
  读 java.lang:type=Runtime 的 VmName = OpenJDK 64-Bit Server VM,SpecVersion = 21,Uptime >= 0:true
  Threading 的 ThreadCount = 6,PeakThreadCount = 6;调用操作 findDeadlockedThreads → null
  GarbageCollector G1 Young Generation:CollectionCount = 0,MemoryPoolNames 个数 = 3
  GarbageCollector G1 Old Generation:CollectionCount = 0,MemoryPoolNames 个数 = 3
  GarbageCollector G1 Concurrent GC:CollectionCount = 0,MemoryPoolNames 个数 = 1
  MBeanInfo(Memory):属性 [ObjectPendingFinalizationCount, HeapMemoryUsage, NonHeapMemoryUsage, Verbose, ObjectName],操作 [gc]

自定义 MBean

实测 · 本机执行输出
  注册 Standard MBean(接口名必须是 类名 + MBean):isRegistered = true
  MBeanInfo:属性 [MaxSize(读写), Name(只读), Size(只读)],操作 [put, clear]
  getAttribute(Name) = demo-cache;setAttribute(MaxSize, 2) 之后 MaxSize = 2
  invoke put:1,2;Size = 2
  第三次 put 抛的是 RuntimeMBeanException,getCause = java.lang.IllegalStateException: cache full
  setAttribute 一个只读属性 Size → AttributeNotFoundException: Read-only attribute: Size
  getAttribute 一个不存在的属性 → AttributeNotFoundException: No such attribute: Nope
  用同一个 ObjectName 再注册一次 → InstanceAlreadyExistsException
  注册一个不符合 MBean 规范的对象 → NotCompliantMBeanException
  clear() 之后 Size = 0
  按模式查询 demo:* → [demo:type=Cache,name=main]

通知

实测 · 本机执行输出
  两次 setAttribute 之后收到的通知:
    MaxSize: 100 → 10 (seq 1,listener 线程 = main)
    MaxSize: 10 → 20 (seq 2,listener 线程 = main)
  通知是在调用 setAttribute 的线程里同步发出的吗:true
  unregisterMBean 之后 isRegistered = false

远程 JMX

实测 · 本机执行输出
  连接成功,用时 105 ms;远程 MBean 数 = 28,远程 JVM 的 pid 属性 Name = 65302@bogon
  远程调用自定义 MBean:Count = 0;invoke incr → 1,2;Count = 2
  远程 getAttribute 1000 次:平均 146.69 µs/次(RMI 往返,回环地址)

分步演示

JMX
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,JMX 远程只开在本机回环、没有认证与 SSL
    • 没有验证:带认证与 SSL 的远程 JMX、Open MBean 与 MXBean 的类型映射、通过 jcmd/jconsole 连接、JMX 的安全风险(只用文字提示,没有演示)、MBean 在大量属性时的性能;耗时是一次运行
    京ICP备2026067502号-1京公网安备11010502063487号