You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMX Notification listener无法正常触发监听的问题排查

问题现象

3个主类分别在独立命令行窗口按Main1→Main2→Main3顺序启动:

  • Main1负责注册MBean
  • Main2负责给目标MBean添加通知监听器
  • Main3负责修改MBean的属性值
    预期执行Main3后,Main2窗口输出Received notification!,实际无任何输出。
相关代码

Main1(注册MBean)

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); 
JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, null); 
connector.connect;
MBeanServerConnection server = connector.getMBeanServerConnection();
ObjectName objNm = new ObjectName("Qwerty:type=server1");
server = createMBean(SampleCnt.class.getName(), objNm);

Main2(添加监听器)

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); 
JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, null); 
connector.connect;
MBeanServerConnection server = connector.getMBeanServerConnection();
ObjectName objNm = new ObjectName("Qwerty:type=server1");
if (server.isRegistered(objNm)) {
   CntListener listener = new CntListener();
   server.addNotificationListener(objNm, listener, null,null);
}

Main3(修改MBean属性)

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); 
JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, null); 
connector.connect;
MBeanServerConnection server = connector.getMBeanServerConnection();
ObjectName objNm = new ObjectName("Qwerty:type=server1");
if (server.isRegistered(objNm)) {
   server.setAttribute(objNm, new Attribute("cnt", 1));
}

配套类定义

SampleCntMBean接口

public interface SampleCntMBean {
   public int getCnt();
   public void setCnt(int cnt);
}

SampleCnt MBean实现类

public class extends NotificationBroadcasterSupport implements SampleCntMBean {
   volatile private int cnt = 0;
   public int getCnt() {
      return cnt;
   }
   public void setCnt(int cnt) {
      this.cnt = cnt;
   }
}

自定义通知监听器

public class CntListener implements NotificationListener {
   public void handleNotification(Notification notification, Object handback) {  
      System.out.println("Received notification!");  
   } 
}
故障原因

监听器未触发的核心问题如下:

  1. MBean属性修改逻辑未主动发送通知
    SampleCnt类虽然继承了NotificationBroadcasterSupport获得了通知发送能力,但setCnt方法仅完成了属性值赋值,没有调用sendNotification()方法发送属性变更事件。JMX的MBean不会自动为属性修改操作触发通知,所有通知都需要业务代码手动构造并发送,监听器没有收到事件自然不会执行打印逻辑。

  2. 代码存在多处语法、API调用错误,会直接导致编译/运行失败

  • 三个主类中的connector.connect;写法语法错误,connect是方法,必须加括号调用:connector.connect();
  • Main1中server = createMBean(SampleCnt.class.getName(), objNm);调用逻辑错误:createMBean是MBeanServerConnection实例的方法,需要通过server.createMBean(...)调用,且该方法返回值为ObjectInstance类型,不能直接赋值给MBeanServerConnection类型的server变量
  • SampleCnt类定义缺失类名,public class extends NotificationBroadcasterSupport需要补全类名:public class SampleCnt extends NotificationBroadcasterSupport
  1. Main2进程生命周期问题
    如果Main2添加完监听器后代码直接执行结束、进程退出,也无法收到后续Main3触发的通知,需要保持Main2进程持续运行等待事件。
修复方式
  1. 修正上述所有语法、API调用错误
  2. 改造SampleCnt类的setCnt方法,属性变更后主动发送属性变更通知,参考实现:
public class SampleCnt extends NotificationBroadcasterSupport implements SampleCntMBean {
   volatile private int cnt = 0;
   // 通知自增序列号
   private long notifySeq = 0;
   public int getCnt() {
      return cnt;
   }
   public void setCnt(int cnt) {
      int oldValue = this.cnt;
      this.cnt = cnt;
      // 构造属性变更通知并发送
      AttributeChangeNotification changeNotify = new AttributeChangeNotification(
        this,
        notifySeq++,
        System.currentTimeMillis(),
        "cnt属性值已修改",
        "cnt",
        "int",
        oldValue,
        cnt
      );
      sendNotification(changeNotify);
   }
}
  1. Main2添加完监听器后,加线程等待逻辑保持进程存活,比如加Thread.sleep(Long.MAX_VALUE);避免进程直接退出。

内容的提问来源于stack exchange,提问作者user4687994

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:06:16