JavaRMI服务器不会从其HTTP代码库服务器动态加载缺少的类
上下文
这是一个使用Java RMI的应用程序,具有:
- 主机A上的客户端和主机B上的服务器
- 作为主机A上的HTTP服务器,它保存客户端和服务器使用的所有类的副本李>
- RMI注册表是从服务器代码创建的,它共享服务器JVM和类路径李>
对于服务器和客户端应用程序:
java.rmi.server.codebase
属性(在代码中)设置为HTTP服务器URL李>- 安全管理器具有适当的策略李>
java.rmi.server.hostname
被设置为LAN地址李>
方法调用:
- 服务器方法是使用类型为
WorkRequest
(抽象类)的参数定义的李> - 客户端使用子类
WorkRequestSquare
调用此方法李> - ^服务器代码中从未提到{
}
服务器代码
Object execute(WorkRequest work) throws RemoteException { return work.execute(); }
客户端代码:
try { servant.execute(new WorkRequestSquare(123)); }
catch (RemoteException e) {
System.out.println("Error while submitting work request:");
e.printStackTrace();
}
当服务器在类路径中有所有相关的类,并且不需要动态加载时,此代码可以工作
问题
从服务器端的类路径中删除WorkRequestSquare
会在客户端引发异常(服务器端不会引发任何异常):
Error while submitting work request:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: WorkRequestSquare
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
...
WorkRequestSquare
由于服务器代码中从未明确提到过,因此它应该是可动态加载的,但这种情况不会发生
旁路
Stuart Marks让我知道属性java.rmi.server.useCodebaseOnly
应该设置为false
此属性的默认值已从false
更改为true
in JDK 7u21useCodebaseOnly
设置为true
可防止JVM从任何位置动态加载类,使用java.rmi.server.codebase
在本地定义的位置除外。这意味着useCodebaseOnly
为true
的服务器将忽略客户机JVM在编组WorkRequestSquare
参数时设置的代码基值
当服务器上的useCodebaseOnly
设置为false
并且从服务器类路径中删除WorkRequestSquare
类时,服务器现在从HTTP服务器获取类定义。这是一个有效的旁路
问题
由于客户端和服务器的codebase
属性值相同,因此仍然存在异常
当useCodebaseOnly
被默认为true
时,服务器JVM应该忽略添加到RMI流中的客户端codebase
,但无论如何,它应该使用自己的codebase
来检索WorkRequestSquare
类
无论如何,这应该是成功的,因为客户机和服务器的codebase
值是相同的
有人能解释一下那件事吗
# 1 楼答案
在客户端代码中按名称实际使用的类。例如,远程接口、形式参数和结果的类型、远程方法签名中命名的异常类型
实现上述类或接口且在客户端代码中不按名称使用的类
确实有一个eclipse插件,我很多年前就看到了,但我从来没有真正需要过