在同一JVM中调用JMX MBean或通过远程方式调用JMX MBean的区别

4
我有几个应用程序在WebLogic服务器上部署。这些应用程序公开了一些JMX MBean。当我通过JConsole或JRMC远程调用这些MBean的操作时,它们能够正常工作。
但由于JMX并不是非常适合防火墙,所以我创建了另一个简单的Servlet应用程序,部署在同一台服务器上,并且调用一组本地MBeans的操作。从servlet中,我使用ManagementFactory.getPlatformMBeanServer()来查找并调用同一JVM中其他应用程序的MBeans,但对于某些操作,我会得到ClassCastException或ClassNotFoundException,这取决于所调用的操作,但有些操作可以正常工作。
有什么想法吗?
1个回答

3
我猜这里发生的情况是,你的servlet线程有一个与你调用的MBeans不同的上下文类加载器。因此,如果MBean属性、操作参数或返回值包含的类型不是核心JVM类(或者不是从相同的根类加载器共享的类),那么你将会得到ClassCast、ClassNotFound和ClassDefNotFound异常。
这个过程可能适用于你。你需要做的是临时将servlet线程的上下文类加载器更改为与MBean从中加载的类加载器相同。一旦调用完成,你可以再把它设置回去。由于你知道目标MBean的ObjectName,MBeanServer会为你提供正确的类加载器。
以下是一个基本示例:
public void callMBean() throws MalformedObjectNameException, NullPointerException, InstanceNotFoundException {
    final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
    try {
        ObjectName targetObjectName = new ObjectName(".....");
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ClassLoader tmpClassLoader = server.getClassLoaderFor(targetObjectName);
        Thread.currentThread().setContextClassLoader(tmpClassLoader);
        // ==========================================
        // Invoke operations here
        // ==========================================
    } finally {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接