注意:我将问题标题更改为更精确
这是我的问题:使用RMI在客户端和服务器之间进行通信时,客户端是否需要在类路径中包含Stub
,或者该Stub
应该只在服务器端吗?
注意,“完整”的故事:
我目前正在开发一个调用计算引擎的Web应用程序。这两个元素之间的通信是使用RMI进行的。
这是项目的Maven结构:
my-project
+- core
+- web-application
+- engine
web-application
和engine
都依赖于core
。在
core
模块中,我定义了一个接口:public interface MyEngine extends java.rmi.Remote {
MyResults calculate() throws RemoteException;
}
在
engine
模块(从RMI角度来看是服务器)中,我定义此接口的实现:public class MyEngineImpl extends UnicastRemoteObject implements MyEngine {
public MyResults calculate() throws RemoteException {
...
}
public static void main(String... args) {
MyEngine engine = new MyEngineImpl();
Registry registry = LocateRegistry.createRegistry(1418);
registry.rebind("my-engine", engine);
}
}
最后,在
web-application
上,我使用core
的接口编写了一个调用引擎模块的类:public class RemoteEngineFacade {
public MyResults callCalculate() throws RemoteException {
Registry localisation = LocateRegistry.getRegistry("url-of-engine", 1418);
MyEngine engine = (LiquidityEngine) localisation.lookup("my-engine");
return engine.calculate();
}
}
RMI编译由
rmic
Maven插件完成:<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rmic-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>rmi compilation</id>
<goals>
<goal>rmic</goal>
</goals>
<configuration>
<outputDirectory>target/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
(请注意,此插件定义是在每个模块上进行的)
现在,在部署应用程序之后,当
web-application
调用engine
时,我在Web应用程序日志中收到以下错误:2012-03-12 09:42:37 ERROR [xxx.RemoteEngineFacade] Engine is unable to respond to the request
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: xxx.MyEngineImpl_Stub (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at xxx.RemoteEngineFacade.callCalculate(RemoteEngineFacade.java:50)
...
我不明白为什么它要在
web-application
侧寻找Stub,因为通常该Stub只能位于RMI服务器上(在我的上下文中为engine
)。你知道我的问题在哪里吗?
谢谢。
编辑:如Riddhish.Chaudhari的回答所述,设置安全管理器可以解决此问题。唯一的区别是我没有安全管理器:stacktrace中的RMI类加载器已禁用消息...
编辑2:如果我在
WEB-INF/lib
中复制engine.jar,则表明通信正确。但是我不必在我的Web应用程序中添加引擎库... 最佳答案
我终于解决了我的问题。 In this page,据说
从J2SE 5.0版本开始,远程对象的存根类不再
需要使用rmic stub编译器进行预生成,除非
远程对象需要支持在5.0之前的VM中运行的客户端
当我使用Java 6时,我决定只删除我的rmic
文件中的pom.xml
任务...,它起作用了!
也许服务器(我的引擎)中存在Stub
会对JVM造成一些混乱,这会产生我得到的错误...
关于java - 为什么RMI客户端需要在其类路径中包含 stub ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9663999/