如何设置 rmiregistry 使用的类路径?

我正在尝试制作一个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 环境变量,该变量不包含要下载到远程对象客户端的任何类的路径。这听起来与我需要的相反...还是我读错了?有没有人成功启动使用第三方jars(在我的情况下,commons-io,commons-logging和rmiio)的RMI客户端/服务器?

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


更新我找到了一种方法来解决这个问题。请参阅下面的答案。


答案 1

有关取消设置 CLASSPATH 的注释仅在使用 RMI 代码库功能时才适用,因为有关下载类的隐晦注释旨在暗示。

如果您没有使用代码库功能,只需执行以下操作之一:

  1. 根据需要设置 CLASSPATH 环境变量,然后再启动,如此处其他位置所示,或者rmiregistry,
  2. 入手rmiregistry-J-Djava.class.path=...
  3. 在服务器JVM中启动注册表,这在很多方面都是最好的解决方案,因为它与JVM一起生存和死亡,共享其类路径,并且顺便符合代码库功能的要求。LocateRegistry.createRegistry().

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


答案 2

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


推荐