2

我在分布式处理工具的范围内遇到了一个涉及 RMI 注册表创建和获取的问题。首先,我将简要描述一下我的环境:

环境
我需要一个后台 Java 进程来永久执行。我的软件实例(在同一台物理机器中)需要与该进程通信才能执行某些操作。几个月前我发现在同一台物理机器上通信不同 JVM 的解决方案是 Java RMI。因此,我启动后台进程并从中创建一个注册表:

    CAEATServiceManagerInterface smi = (CAEATServiceManagerInterface)UnicastRemoteObject.exportObject(csm, 0);
    Registry registry = LocateRegistry.createRegistry(8090);            
    registry.rebind("ServiceManager", smi);

注意:csm是要导出的远程对象。安全策略已正确安装(所有人的 AllPermission),RMISecurityManager 也已正确安装。

现在,我的主程序的实例能够在任何给定时刻查找注册表并获取远程对象:

    Registry registry = LocateRegistry.getRegistry(8090);
    smi = (CAEATServiceManagerInterface)registry.lookup("ServiceManager");

问题
当我的程序(获取注册表的主程序和创建它的后台程序)从 jar 文件中执行时,就会出现问题。如果它们是从 Eclipse 执行的,则一切正常。如果它们直接从命令行执行,也可以。但是当它们被打包成一个自动执行的 jar 文件进行分发时,后台进程似乎可以很好地创建注册表,但是当主程序尝试查找它时,会发生这种情况:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.io.EOFException
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at sener.caeat.autoejecutable.PublicadorStandalone.getServiceManagerInterface(PublicadorStandalone.java:170)
    at sener.caeat.autoejecutable.PublicadorStandalone.publicarEsquema(PublicadorStandalone.java:319)    
    at sener.caeat.autoejecutable.CargadorStandalone.mostrarDialogoOpcionesPublicacion(CargadorStandalone.java:415)
    at sener.caeat.autoejecutable.ExtractorJars.main(ExtractorJars.java:32)
Caused by: java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1296)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    at sun.rmi.server.MarshalInputStream.readLocation(MarshalInputStream.java:285)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:228)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    ... 5 more

忘记我的课程,我不明白的是 EOFException ...为什么它只在程序从 jar 中执行时才启动?

附加数据:如果后台程序是从jar文件中启动的,但是查找注册表的主程序是从Eclipse启动的,问题仍然存在。

提前致谢。

4

2 回答 2

0

最后我找到了解决方案。它与 RMI 没有直接关系,但与我的程序被打包到一个可自动执行的 jar 文件中的方式有​​关。

我的子流程的特点之一是它使用自定义 RMI 类加载器来处理与自定义远程类解析相关的一些内容。这是通过以下语句实现的:

System.setProperty("java.rmi.server.RMIClassLoaderSpi","<My_custom_RMI_ClassLoader>");

请记住:这是从 jar 文件中执行的。“My_c​​ustom_RMI_ClassLoader”类在 jar 中,这就是抛出的异常不是 ClassNotFoundException 的原因。但是,我的错误来了,这个类里面有一个内部类(其中一个名字以 $innerClass.class 结尾)。并且那个 .class 文件没有被打包在 JAR 文件中。我想这就是解析代理类时出现 EOFException 的原因。

非常感谢,但问题比我想象的要微妙。

于 2012-09-27T00:01:17.193 回答
0

这通常是由与另一端的 SocketPermissions 相关的 SecurityExceptions 引起的,导致传入的连接过早关闭。看看它的日志。

于 2012-09-26T02:05:19.060 回答