我在分布式处理工具的范围内涉及RMI注册表创建和获取问题。首先,我将简要介绍一下我的环境:
环境
我需要一个永久执行的后台Java进程。我的软件实例(在同一物理机器中)需要与该进程通信才能执行某些操作。我几个月前发现的在同一台物理机器上通信不同JVM的解决方案是Java RMI。因此,我启动后台进程并从中创建一个注册表:
CAEATServiceManagerInterface smi = (CAEATServiceManagerInterface)UnicastRemoteObject.exportObject(csm, 0);
Registry registry = LocateRegistry.createRegistry(8090);
registry.rebind("ServiceManager", smi);
注意: csm 是要导出的Remote对象。安全策略已正确安装(AllPermission适用于所有人),因此一直是RMISecurityManager。
现在,我的主程序的实例能够在任何给定时刻查找注册表并获取Remote对象:
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启动Lookups the Registry的主程序,那么问题仍在那里。
提前致谢。
答案 0 :(得分:0)
这通常是由与另一端的SocketPermissions相关的SecurityExceptions引起的,导致传入连接过早关闭。看看它的日志。
答案 1 :(得分:0)
最后我找到了解决方案。它与RMI没有直接关系,但是我的程序被打包到一个可自动执行的jar文件中。
我的子流程的一个特点是它使用自定义RMI ClassLoader来处理与自定义远程类解析相关的一些东西。这是通过以下声明实现的:
System.setProperty("java.rmi.server.RMIClassLoaderSpi","<My_custom_RMI_ClassLoader>");
请记住:这是从jar文件中执行的。类“My_custom_RMI_ClassLoader”在jar中,这就是为什么抛出的异常不是ClassNotFoundException。但是,这就是我的错误,这个类里面有一个内部类(其中一个名字以$ innerClass.class结尾)。那个.class文件没有包含在JAR文件中。我想这是代理类解析时EOFException的原因。
非常感谢,但问题比我想象的更微妙。