如何为JMX中Memory MBean的HeapMemoryUsage内的committed属性添加监听器?
正确监听HeapMemoryUsage中committed属性变化的方法
你之前的代码报错,核心问题是把CompositeData的子属性当成了独立的MBean——HeapMemoryUsage是java.lang:type=Memory这个标准MXBean的一个属性,并非一个单独的MBean实例,所以java.lang:type=Memory,name=HeapMemoryUsage.committed这个ObjectName对应的MBean根本不存在,自然会抛出InstanceNotFoundException。
要监听committed属性的变化,你需要监听原Memory MBean的HeapMemoryUsage属性,然后在监听器中解析CompositeData,提取committed的值。具体有两种常用方式:
方式一:使用AttributeChangeNotificationListener(推荐)
这种方式直接利用JMX的属性变化通知机制,监听HeapMemoryUsage属性的变化,再从中提取committed值:
// 获取MBean服务器连接 MBeanServerConnection connection = jmxConnector.getMBeanServerConnection(); ObjectName memoryMBeanName = new ObjectName("java.lang:type=Memory"); // 创建属性变化监听器 AttributeChangeNotificationListener committedListener = (notification, handback) -> { // 确认是属性变化通知 if (AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(notification.getType())) { AttributeChangeNotification attrNotify = (AttributeChangeNotification) notification; // 过滤出HeapMemoryUsage属性的变化 if ("HeapMemoryUsage".equals(attrNotify.getAttributeName())) { CompositeData newHeapUsage = (CompositeData) attrNotify.getNewValue(); Long newCommittedValue = (Long) newHeapUsage.get("committed"); // 这里处理committed值的变化逻辑 System.out.println("Heap committed memory updated to: " + newCommittedValue + " bytes"); } } }; // 注册监听器,同时添加过滤器只接收HeapMemoryUsage的变化通知 connection.addNotificationListener( memoryMBeanName, committedListener, // 通知过滤器:只保留HeapMemoryUsage的属性变化通知 notification -> { if (notification instanceof AttributeChangeNotification) { AttributeChangeNotification acn = (AttributeChangeNotification) notification; return "HeapMemoryUsage".equals(acn.getAttributeName()); } return false; }, null // 可选的回传对象,这里不需要 );
关键说明:
- 我们监听的还是
java.lang:type=Memory这个真实存在的MBean。 HeapMemoryUsage作为CompositeData类型的属性,当内存使用情况变化时,JMX会发送AttributeChangeNotification。- 通过过滤器可以减少不必要的通知处理,只关注我们关心的属性。
方式二:自定义通知转发(复杂场景可选)
如果你的业务需要更细粒度的监听(比如只在committed值真正变化时触发逻辑),可以自己封装一个小逻辑,在监听器中对比前后committed的值:
// 保存上一次的committed值,用于对比 private Long lastCommittedValue; // 在监听器中添加对比逻辑 AttributeChangeNotificationListener committedListener = (notification, handback) -> { if (AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(notification.getType())) { AttributeChangeNotification attrNotify = (AttributeChangeNotification) notification; if ("HeapMemoryUsage".equals(attrNotify.getAttributeName())) { CompositeData newHeapUsage = (CompositeData) attrNotify.getNewValue(); Long currentCommitted = (Long) newHeapUsage.get("committed"); // 只有当值真正变化时才处理 if (lastCommittedValue == null || !lastCommittedValue.equals(currentCommitted)) { System.out.println("Heap committed memory changed: " + lastCommittedValue + " -> " + currentCommitted); lastCommittedValue = currentCommitted; } } } };
这种方式可以避免因为CompositeData对象本身引用变化但committed值未变时触发不必要的逻辑。
内容的提问来源于stack exchange,提问作者Carla
相关产品推荐
相关产品推荐

