15

我正在尝试制作一个 Java RMI 客户端/服务器应用程序。我在启动我的应用程序的服务器端时遇到了问题,因为当我尝试启动应用程序的服务器端时,它在调用 Registry.bind() 方法期间一直遇到ClassNotFoundException 。

我从这里的简单教程开始:http: //docs.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html。遵循这些说明后,它最初抛出 ClassNotFoundException 抱怨找不到“example.hello.Hello”。我能够通过从教程中的destDir目录启动 rmiregistry 来解决这个问题,因为 rmiregistry 显然将其初始起始目录用作其类路径的一部分。

之后我开始使用我的另一个测试应用程序,直到我开始在我的服务器类中使用第三方 jar 文件之前我都很好。现在,如果我的服务器类引用任何 jar 文件中的任何内容,则 Registry.bind() 将引发 ClassNotFoundException,因为 rmiregistry 应用程序不知道这些 jar 文件。

据我所知, rmiregistry 不接受任何类型的类路径启动参数,所以我想知道如何告诉它我希望它承认什么类路径。根据此处的教程:http: //docs.oracle.com/javase/tutorial/rmi/running.html,“您必须确保运行 rmiregistry 的 shell 或窗口没有设置 CLASSPATH 环境变量,或者有一个 CLASSPATH 环境变量,其中不包括您希望下载到远程对象客户端的任何类的路径。” 这听起来与我需要的相反……还是我读错了?是否有人成功启动了使用第三方 jar(commons-io、commons-logging 和 rmiio,在我的情况下)的 RMI 客户端/服务器?

顺便说一句,这是在 Windows 上。


更新 我找到了解决方法。请看下面我的回答。

4

4 回答 4

5

有关取消设置 CLASSPATH 的注释仅适用于您使用 RMI 代码库功能,因为有关下载类的神秘注释旨在暗示。

如果您不使用代码库功能,只需:

  1. 在开始之前根据需要设置 CLASSPATH 环境变量,rmiregistry,如此处其他地方所示,或者
  2. 开始rmiregistry_-J-Djava.class.path=...
  3. 在你的服务器 JVM 中启动 Registry,LocateRegistry.createRegistry().这在很多方面都是最好的解决方案,因为它与 JVM 一起存在和死亡,共享它的类路径,并且顺便也符合代码库特性的要求。

如果做(3),则必须将返回值存储到静态变量中,以防止它被垃圾回收,从而导致注册表无法导出,从而导致远程对象的 DGC,从而导致它被GC'd,这将导致监听线程退出,这可能导致整个JVM退出。

于 2014-05-14T00:26:11.083 回答
4

没有 RMI Registry 特定的 java 类路径。它应该使用与 Java 系统的其余部分相同的类路径。您可以通过在命令行或操作系统环境中指定类路径来设置它。虽然有点过时,但该文档应该为您指明正确的方向。

于 2012-12-11T22:09:05.273 回答
4

(我最初将此答案发布为对我的问题的更新。根据 Zecas 在其中一条评论中的建议,我将其移至答案部分。)

通过不遵守上面我的问题中引用的第二个教程中的建议,我能够启动服务器部分:

“您必须确保您将在其中运行 rmiregistry 的 shell 或窗口没有设置 CLASSPATH 环境变量,或者有一个 CLASSPATH 环境变量,其中不包含您希望下载到远程对象客户端的任何类的路径。”

我创建了一个 CLASSPATH 环境变量,并将我的 .class 输出目录和每个第三方 jar 文件添加到其中。我以为我以前曾尝试过,但我想没有……只是想我会留下我的解决方案,以防其他人遇到同样的问题。

于 2013-12-02T20:40:34.493 回答
1

如何为 rmiregistry 设置类路径的示例

赢32:

set CLASSPATH=c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar 

UNIX:

setenv CLASSPATH /home/ann/src:/home/ann/public_html/classes/compute.jar
于 2014-05-13T23:02:38.690 回答