【问题标题】:*adding* a file causes java.lang.ClassNotFoundException in RMI server*添加*一个文件在 RMI 服务器中导致 java.lang.ClassNotFoundException
【发布时间】:2013-11-05 07:29:42
【问题描述】:

我正在尝试设置一个曾经有效但现在出现奇怪行为的 RMI 应用程序。 当我在没有存根的情况下运行它时,我得到 java.lang.ClassNotFoundException: HelloInterface 然后我在目录中添加一个新文件(Hello_Stub)(通过使用 rmic), 然后我得到 java.lang.ClassNotFoundException: Hello_Stub

WTF?? 当它丢失时,它并没有抱怨 Hello_Stub 丢失;但是当我添加该文件时,它开始抱怨它不存在。嗯?

下面是来自终端的文字记录。首先你会看到一个错误;然后我列出当前目录中的文件;然后我生成存根文件并向您展示;然后你会看到它抱怨刚刚添加的文件丢失的错误:

sjudd@kearnsgroup:/kearnsgroup/www/RMItest/classes> java HelloServer
initializing Hello class: Hello, world!
Hello Server failed: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: HelloInterface


sjudd@kearnsgroup:/kearnsgroup/www/RMItest/classes> ll
total 32
-rw------- 1 sjudd sjudd 765 Oct 25 19:52 Hello.class
-rw------- 1 sjudd sjudd 967 Oct 25 19:52 HelloClient.class
-rw-r----- 1 sjudd sjudd 614 Oct 25 19:42 HelloClient.java
-rw------- 1 sjudd sjudd 222 Oct 25 19:52 HelloInterface.class
-rw-r----- 1 sjudd sjudd 360 Oct 25 09:08 HelloInterface.java
-rw-r----- 1 sjudd sjudd 847 Oct 25 09:56 Hello.java
-rw------- 1 sjudd sjudd 916 Oct 25 19:52 HelloServer.class
-rw-r----- 1 sjudd sjudd 439 Oct 25 09:14 HelloServer.java


sjudd@kearnsgroup:/kearnsgroup/www/RMItest/classes> rmic Hello
sjudd@kearnsgroup:/kearnsgroup/www/RMItest/classes> ll
total 36
-rw------- 1 sjudd sjudd  765 Oct 25 19:52 Hello.class
-rw------- 1 sjudd sjudd  967 Oct 25 19:52 HelloClient.class
-rw-r----- 1 sjudd sjudd  614 Oct 25 19:42 HelloClient.java
-rw------- 1 sjudd sjudd  222 Oct 25 19:52 HelloInterface.class
-rw-r----- 1 sjudd sjudd  360 Oct 25 09:08 HelloInterface.java
-rw-r----- 1 sjudd sjudd  847 Oct 25 09:56 Hello.java
-rw------- 1 sjudd sjudd  916 Oct 25 19:52 HelloServer.class
-rw-r----- 1 sjudd sjudd  439 Oct 25 09:14 HelloServer.java
-rw------- 1 sjudd sjudd 1635 Oct 25 20:34 Hello_Stub.class


sjudd@kearnsgroup:/kearnsgroup/www/RMItest/classes> java HelloServer
initializing Hello class: Hello, world!
Hello Server failed: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: Hello_Stub

请注意,这里失败的是 rmi SERVER,而不是客户端。

这段代码在一台机器(Mac)上运行良好,但是当复制到另一台机器(Linux)时,它会抛出这个惊人的错误。

我被这种奇怪的感觉吓坏了,我不知道如何处理它。这可能与解组步骤有关吗?还是使用环境变量?也许是类路径?我看不出要寻找什么。有什么疯狂的理论吗?

【问题讨论】:

  • linux机器的classpath中有你的类吗?

标签: java rmi classnotfoundexception stub


【解决方案1】:

不要添加存根。从 Java 1.5 开始就不需要了。只需确保您遵循UnicastRemoteObject. 的 Javadoc 序言中概述的要求即可。最初的问题是由于远程接口类在注册表或客户端的 CLASSPATH 上不可用,或两者兼而有之。

【讨论】:

  • 非常感谢。你把手指放在问题上。关于 RMI 的各种教程都说要启动 rmiregistry,但我所依赖的那些确实详细说明了在哪里启动。 rmir​​egistry 总是毫无问题地启动,并且在您尝试启动服务器之前问题并不明显。此时,抛出的异常并没有暗示它们是由另一个进程中的某些东西引起的!
  • 尽管如此,上面的谜题仍然是一个完全令人费解的行为。是的,我在错误的地方启动 rmiregistry 是有罪的,但它最终导致的症状是加载器找不到我刚刚放入其路径的类。它显然是对相关课程存在的事实做出反应,并声称它同时不存在!这完全令人费解——即使现在我知道如何避免它。当然,有些东西可以比我们得到的信息更有用。
  • (a) 确实有一个提示:堆栈跟踪中的ServerException。 (b) 如果创建存根,服务器在导出时需要它;绑定时注册表需要它;客户在查找时需要它。这同样适用于远程接口本身和它所依赖的所有应用程序类,以此类推,直到关闭。
  • 谢谢 EJP;您的额外提示正在慢慢说服这种疯狂背后有一个迂回的方法。
【解决方案2】:

我启动 rmiregistry 时没有注意它的类路径。 通过 cd'ing 到 classes 目录并从那里启动它,所有问题都消失了。

我相信您可以使用为 rmiregistry 程序指定 CLASSPATH 或代码库的标志来完成同样的事情。有谁知道语法?我已经尝试过这些(不成功):

rmir​​egistry -JCLASSPATH="路径/到/类/"
rmir​​egistry -JCLASSPATH="/absolute/path/to/classes/"
rmir​​egistry -J-DCLASSPATH="path/to/classes/"
rmir​​egistry -J-DCLASSPATH="/absolute/path/to/classes/"

它们都会导致java.lang.ClassNotFoundException: BNS.plumbing.SessionHostInterface 当服务器开始运行时。 (至少这是行为。)

【讨论】:

  • -classpath 选项是java 命令的命令行选项(不是属性),它需要一个单独的参数。要将这些参数从rmiregistry 传递给java,请执行以下操作:rmiregistry -J-classpath -Jpath/to/your/classes
猜你喜欢
  • 2017-05-22
  • 2023-04-08
  • 2023-04-02
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 2013-07-14
  • 2023-03-17
  • 2021-08-03
相关资源
最近更新 更多