0

据我了解,我在客户端设置的 RMI 代码库将传递给服务器。然后服务器使用这个代码库来定位不在服务器类路径中的类。

只要服务器类路径中所有必需的类都可用,远程方法调用就可以正常工作。然后,我尝试从服务器类路径中删除所需的类,而是在启动 RMI 客户端时在 codebase 属性中指定所需类的新位置。不幸的是,这会给我一个 ClassNotFoundException: java.lang.ClassNotFoundException: client.Pi

堆栈跟踪:

java.rmi.ServerException: RemoteException occurred in server thread; nested exce
ption is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
java.lang.ClassNotFoundException: client.Pi
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Sou
rce)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Sour
ce)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknow
n Source)
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn
own Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at com.sun.proxy.$Proxy0.executeTask(Unknown Source)
at client.ComputePi.main(ComputePi.java:26)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested ex
ception is:
java.lang.ClassNotFoundException: client.Pi
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Sou
rce)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Sour
ce)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: client.Pi
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler$Loader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClassForName(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader$2.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader.loadClass(Unknown Source)
at sun.rmi.server.MarshalInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source)
... 11 more

启动服务器:

C:\TEMP\RMI\RMIDemo\src>java 
-cp C:\Users\samue_000\public_html\classes\compute.jar;C:\TEMP\RMI\RMIDemo\src 
-Djava.security.policy=server.policy 
-Djava.rmi.server.useCodebaseOnly=false  
engine.ComputeEngine

>> ComputeEngine bound

启动客户端:

C:\TEMP\RMI\RMIDemo\src>java 
-cp C:\Users\samue_000\public_html\classes\compute.jar;c:\Temp\RMI\RMIDemo\src;c:\temp 
-Djava.security.policy=client.policy 
-Djava.rmi.server.codebase=file:/C:/Users/samue_000/public_html/classes 
client.ComputePi

在客户端的类路径 (c:\temp) 中包含客户端也需要的所需的 client.Pi 类。为了告诉服务器这个类所在的位置,我将一个副本放在一个单独的文件夹中,并使用 codebase 属性指定了这个文件夹。该类的确切位置是 C:/Users/samue_000/public_html/classes/client/Pi.class。它都在同一台物理机器上运行(没有虚拟机)。所以我不明白为什么服务器没有从客户端获取代码库并加载所需的 client.Pi 类。

我试图将发布的信息最小化到所需的部分,以免过度填充这篇文章。如果需要更多信息来帮助我解决此问题,请告诉我。这让我快疯了。我在这个问题上工作了几个小时和几天......

编辑:我使用了与oracle的这篇文章中描述的几乎相同的代码。唯一的区别是我以编程方式创建 rmi 注册表,而不是单独启动注册表。所以代码本身应该没有任何问题。只要 Pi 类位于服务器的类路径中,它就可以正常工作。但是一旦 Pi 类只存在于代码库和客户端的类路径中,它就不再起作用了。

4

3 回答 3

3

通常 RMI 代码库 URL 是 HTTP URL,它们通常引用 JAR 文件,而不是目录。

-Djava.rmi.server.codebase=file:/C:/Users/samue_000/pubic_html/classes 

那是一个file:URL,它只能在它适用的同一系统上工作。如果服务器在不同的主机上,它不会成为头或尾。

但是,由于它们都在同一台机器上,它应该可以工作。能发一下远程接口吗?

于 2014-05-21T22:45:31.707 回答
0

最后不要省略 / ,然后尝试:

-Djava.rmi.server.codebase=file:/C:/Users/samue_000/public_html/classes/ 
于 2020-05-24T14:06:30.283 回答
-1

您可以下载类文件。但是您需要使用路径分隔符终止路径。这就是文档状态。这应该是一条评论,但在我达到 50 点声望点之前,我已经失去了对该网站发表评论的权利。

于 2019-09-03T07:36:08.220 回答