【问题标题】:How to safely handle missing local classes in JMX remote clients如何安全地处理 JMX 远程客户端中缺少的本地类
【发布时间】:2012-12-30 18:50:26
【问题描述】:

我一直在玩一个可编程的远程 JMX 客户端,它连接到 WebSphere Application Server 的 MBean 服务器。到目前为止一切顺利,我可以使用适当的 JMXServiceURL 进行连接并订阅来自我的 bean 的通知。

但是 - 如果一个 bean 发送一个通知,其中包含一个不在我的本地类路径中的类,它会因堆栈跟踪而崩溃:

SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.RemoteException: CORBA NO_IMPLEMENT 1330646337 No; nested exception is: 
    org.omg.CORBA.NO_IMPLEMENT: The sender's class RMI:com.mycompany.MyWeirdClass:143EC4C84209B825:EAD08F0965BC6044 is not present on the local classpath, and the class is not marked as truncatable, so it cannot be unmarshaled.  vmcid: OMG  minor code: 1  completed: No
java.rmi.RemoteException: CORBA NO_IMPLEMENT
... more frames ...

这最终是由以下原因引起的:

Caused by: java.lang.ClassNotFoundException: com.mycompany.MyWeirdClass
    at com.ibm.rmi.util.RepositoryId.loadClass(RepositoryId.java:675)
    at com.ibm.rmi.util.RepositoryId.checkClassCache(RepositoryId.java:644)
    ...

看起来它在 IBM 的代码深处爆炸了,而且似乎没有任何地方我可以做任何事情;有问题的通知永远不会到达我的 NotificationListener。

所以;在不阻止我收到进一步通知的情况下,我该如何处理这种情况?

【问题讨论】:

    标签: websphere rmi jmx classnotfoundexception corba


    【解决方案1】:

    我可以想出 4 种方法来解决这个问题,按复杂度升序排列(我认为):

    将类库添加到客户端类路径

    陈述显而易见,但力求全面。

    修改通知

    考虑修改服务器生成的通知,将 com.mycompany.MyWeirdClass 实例换成格式化字符串。如果对象很复杂,请考虑使用 XML 或 JSON。如果您可以修改通知发送者以编组实例,那可能是最简单的。如果没有,您可以修改 com.mycompany.MyWeirdClass 类(应该是 Serializable,对吗?)并添加一个返回实例的字符串表示形式的 writeReplace 方法。

    远程类加载器

    在您的 WebSphere 应用程序中实现一个 HTTP 服务器,该服务器返回包含 com.mycompany.MyWeirdClass 类及其所有依赖项的 JAR。 (从技术上讲,HTTP 服务器可以在任何地方,只要它提供正确的类。)假设 JAR 在 http://classloader.mycompany.com/Weird.jar 上可用。 。现在使用添加的系统属性启动您的客户端,如下所示:

    java .....  -D-Djava.rmi.server.codebase=http://classloader.mycompany.com/Weird.jar ...
    

    有一个提供动态类加载的 HTTP 服务器实现示例here

    将类实现为 JMX OpenType

    最常见的方法是使类成为MXBean,或者您可以实现CompositeData 或扩展CompositeDataSupport。如果您不介意使用 com.sun 类,java 运行时 (1.6+) 包含 DefaultMXBeanMappingFactory,它将为您创建一个复合数据实例,因此这个有用的实用程序可以与上述解决方案之一。例如,您可以像这样实现 writeReplace 轨道:

    import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
    import com.sun.jmx.mbeanserver.MXBeanMapping;
    final MXBeanMapping mapping = 
       DefaultMXBeanMappingFactory.DEFAULT.mappingForType(
          com.mycompany.MyWeirdClass.class, 
          DefaultMXBeanMappingFactory.DEFAULT
       );
    private Object writeReplace() throws ObjectStreamException {
       try {
          return mapping.toOpenValue(this);
       } catch (Exception ex) {
          throw new RuntimeException(ex);
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      相关资源
      最近更新 更多