从多个MBean服务器取消注册MXBean时的NPE

时间:2015-01-27 14:47:52

标签: java jmx mxbean

我有一个MXBean实例,它在2个MBean服务器中注册:

@MXBean(true)
public interface I {
    // ...
}

public final class C extends StandardMBean implements I {
    public C() {
        super(I.class, JMX.isMXBeanInterface(I.class));
    }

    public static void main(final String args[]) throws JMException, IOException {
        final MBeanServer mBeanServer0 = ManagementFactory.getPlatformMBeanServer();
        final MBeanServer mBeanServer1 = MBeanServerFactory.createMBeanServer();

        final ObjectName objectName = new ObjectName("com.example:name=Foo,type=Bar");
        final I i = new C();
        mBeanServer0.registerMBean(i, objectName);
        mBeanServer1.registerMBean(i, objectName);
        // ...
    }
}

StandardMBean实例包装MXBeanSupport的实例。我想稍后从两个服务器取消注册我的MBean:

mBeanServer1.unregisterMBean(objectName);
mBeanServer0.unregisterMBean(objectName);

问题是,unregister() MXBeanSupport方法具有以下实现,显然只能被称为一次

@Override
public void unregister() {
    synchronized (lock) {
        if (mxbeanLookup != null) {
            if (mxbeanLookup.removeReference(objectName, getResource()))
                objectName = null;
        }
    }
}

否则,我将NPE包裹在RuntimeMBeanException

Exception in thread "main" javax.management.RuntimeMBeanException: RuntimeException thrown in postDeregister method: rethrowing <java.lang.NullPointerException>, although the MBean is sucessfully unregistered
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.postDeregisterInvoke(DefaultMBeanServerInterceptor.java:1060)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.exclusiveUnregisterMBean(DefaultMBeanServerInterceptor.java:452)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.unregisterMBean(DefaultMBeanServerInterceptor.java:415)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.unregisterMBean(JmxMBeanServer.java:546)
    at com.example.C.main(C.java:41)
Caused by: java.lang.NullPointerException
    at com.sun.jmx.mbeanserver.MXBeanLookup.removeReference(MXBeanLookup.java:159)
    at com.sun.jmx.mbeanserver.MXBeanSupport.unregister(MXBeanSupport.java:169)
    at javax.management.StandardMBean.postDeregister(StandardMBean.java:1137)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.postDeregisterInvoke(DefaultMBeanServerInterceptor.java:1054)
    ... 4 more

但是,仅从单个服务器取消注册MBean不是一种选择。

如何在不创建两个单独的MBean实例的情况下更正代码?

1 个答案:

答案 0 :(得分:0)

似乎MBeans基于名称是全局的,因此您将无法从“单个实例”注册,而是从所有可用的上下文中取消注册。

    mBeanServer1.unregisterMBean(objectName);
    mBeanServer0.unregisterMBean(objectName);  // this call is superfluous