我正在尝试制作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不接受任何类型的路径启动arg,所以我想知道如何告诉它我想要它承认什么类路径。根据这里的教程:http://docs.oracle.com/javase/tutorial/rmi/running.html,“您必须确保运行rmiregistry的shell或窗口具有 no CLASSPATH环境变量集或有一个CLASSPATH环境变量,它不包含你想要下载到远程对象客户端的任何类的路径。“这听起来与我需要的相反......或者我读错了吗?有没有人有任何成功启动使用第三方jar的RMI客户端/服务器(在我的情况下,commons-io,commons-logging和rmiio)?
这是在Windows上,顺便说一下。
的更新
我找到了解决方法。请参阅下面的答案。
答案 0 :(得分:5)
关于取消设置CLASSPATH的注释仅适用于您使用RMI代码库功能的情况,因为关于下载类的含义是有意义的。
如果您不使用代码库功能,只需:
rmiregistry,
之前根据需要设置CLASSPATH环境变量,如此处其他地方所示,或rmiregistry
-J-Djava.class.path=...
LocateRegistry.createRegistry().
在服务器JVM中启动注册表这在很多方面都是最佳解决方案,因为它与JVM一起生存和死亡,共享其类路径,并且顺便提一下符合代码库功能的要求好。如果你做(3),你必须将返回值存储到一个静态变量中,以防止它被垃圾收集,这会导致注册表被取消导出,这可能导致远程对象的DGC,这可能导致它是GC' d,这将导致监听线程退出,这可能导致整个JVM退出。
答案 1 :(得分:4)
没有特定于RMI Registry的java类路径。它应该使用与Java系统其余部分相同的类路径。您可以通过在命令行或OS环境中指定类路径来设置类路径。虽然有点过时,但doc应指向正确的方向。
答案 2 :(得分:4)
(我最初发布这个答案是对我的问题的更新.Per Zecas在其中一条评论中的建议,我正在将其移至答案部分。)
我能够通过违反上述问题中引用的第二个教程中的建议来启动服务器部分:
“您必须确保将运行的shell或窗口 rmiregistry要么 否 CLASSPATH环境变量设置或 有一个CLASSPATH环境变量,不包含路径 您希望下载到远程客户端的任何类 对象“。
我创建了一个CLASSPATH环境变量,并将我的.class输出目录和每个第三方jar文件添加到其中。我以为我以前曾尝试过,但我猜不是......只是想我会留下我的解决方案以防其他人遇到同样的问题。
答案 3 :(得分:1)
如何为rmiregistry
设置类路径的示例的Win32:
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