【问题标题】:Java RMI codebase not workingJava RMI 代码库不工作
【发布时间】:2014-07-10 19:01:33
【问题描述】:

据我了解,我在客户端设置的 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 的 article 中描述的几乎相同的代码。唯一的区别是我以编程方式创建 rmi 注册表,而不是单独启动注册表。所以代码本身应该没有任何问题。只要 Pi 类位于服务器的类路径中,它就可以正常工作。但是一旦 Pi 类只存在于代码库和客户端的类路径中,它就不再起作用了。

【问题讨论】:

    标签: java rmi classnotfoundexception codebase


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我使用的确切远程接口可以在这里找到:docs.oracle.com/javase/tutorial/rmi/designing.html(另见我刚刚添加的问题的编辑=)根据oracle的文档,文件协议也应该支持: docs.oracle.com/javase/7/docs/technotes/guides/rmi/… 无论如何我会尝试使用 jar 而不是类文件和 http 路径。
    • 我没有说文件:不支持协议,但它只在单个机器中有用,整个代码库功能基本上没有意义。
    • 谢谢 EJP。现在可以了。正如你所说,因为我没有使用 jar 文件和 class 文件。但我实际上不明白为什么 RMI 需要整个类定义而不仅仅是类的接口?
    • @Sam 当然,因为 JVM 必须执行代码。它无法执行不存在的代码。
    【解决方案2】:

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

    【讨论】:

    【解决方案3】:

    最后不要省略/,试试:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-30
      • 2012-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多