1

我一直在玩一个可编程的远程 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。

所以; 在不阻止我收到进一步通知的情况下,我能做些什么来处理这种情况?

4

1 回答 1

3

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

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

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

修改通知

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

远程类加载器

在您的 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 服务器实现示例。

将类实现为 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);
   }
}
于 2013-01-16T14:51:02.377 回答