JavaRMI:setup方法立即返回,RMI线程为';t创造
我正在尝试设置一个简单的RMI服务器,它绑定到注册表,以便客户端获取所有进一步的通信。我使用的代码如下:JavaRMI:setup方法立即返回,RMI线程为';t创造,java,rmi,Java,Rmi,我正在尝试设置一个简单的RMI服务器,它绑定到注册表,以便客户端获取所有进一步的通信。我使用的代码如下: public class RMIServer implements ServerInterface { static Registry reg; public static void main(String[] args) throws NoSuchObjectException { //Registry reg; try {
public class RMIServer implements ServerInterface {
static Registry reg;
public static void main(String[] args) throws NoSuchObjectException {
//Registry reg;
try {
reg = LocateRegistry.createRegistry(1099);
System.out.println("Registry created.");
} catch (RemoteException ex) {
System.err.println("Registry already existed.");
return;
}
ServerInterface server = new RMIServer();
ServerInterface stub;
try {
stub = (ServerInterface)UnicastRemoteObject.exportObject(server, 0);
} catch (RemoteException ex) {
System.err.println("Could not create stub.");
ex.printStackTrace();
return;
}
try {
reg.rebind("server", stub);
System.out.println("Server bound to registry.");
} catch (RemoteException ex) {
System.err.println("Could not bind server to registry.");
ex.printStackTrace();
//UnicastRemoteObject.unexportObject(server, true);
return;
}
}
...
}
当在我的本地机器上进行测试时,这工作得非常好,我能够在(本地)客户端和服务器之间建立连接。上面的main方法将不会退出,直到我手动终止它,这是预期的行为。我的本地机器(Win8)运行Java 1.7.0_17 64位
现在,当我使用OpenJDK(版本1.7.0_55 64位)在Ubuntu12.04服务器上执行上述代码时,主方法和整个JVM立即退出,RMI线程不运行。不打印错误消息;我只收到有关正在创建注册表和服务器绑定到注册表的消息。显然,客户端无法连接,因为服务器上没有运行RMI进程
据我所知,只要有我没有再次未报告的导出对象,main方法就不应该自动退出。然而,在我的一台机器上,它确实如此
有人知道我在这里遗漏了什么吗
谢谢大家!
更新1:
(抱歉,最近很忙,直到现在才有机会进一步了解此内容)。这个问题在Java6、7、OpenJDK和Sun的版本中仍然存在,即使在更新到Ubuntu 14.04之后也是如此
然而,我设法在云中托管的一台完全不同的机器上重现了这个问题,该机器也运行Ubuntu服务器14.04 x64(尽管除了java安装外,几乎完全干净)。不过,我仍在试图弄清楚如何准确地复制它(当我知道更多信息时,会更新)
在两台机器上重新启动系统时,问题消失了(似乎是暂时的)。
出于完整性考虑:奇怪的是,当系统日志级别设置为FINE或FINEST时,代码突然表现出预期的行为。我还是被难住了 将'reg'变量设为静态。否则,它很容易被GC和DGC撤销,这将导致服务器的DGC及其撤销,进而导致套接字关闭和侦听线程退出。除了我遇到多个(严重的)问题之外,我无法提供任何真正的见解粘贴中OpenJDK Java实现的问题。如果您可以切换到Sun/Oracle JRE(即使只是为了测试),您的问题很可能会自动解决。谢谢-我已经切换到Oracle Java,确保从机器上删除OpenJDK-结果相同。我在哪台机器上编译源代码也没有区别;它在一台机器上工作,但在另一台机器上不工作。我刚刚用java-6-openjdk-i386在Ubuntu12.04上尝试了你的代码,它的行为与你预期的一样,即进程不会退出,并开始在两个端口(注册表和绑定对象)上侦听。RMI的完整日志记录可能会有所帮助,正如另一条评论中所建议的:有关详细信息,请参阅。无论是什么原因,您都可以通过在设置代码后的无限循环中放置一个sleep()来一次性解决此问题。有趣的是,您能否详细说明为什么reg变量会超出范围并符合GC条件?@ChristopheD您自己刚刚说过。现在它是一个局部变量,所以当main()退出时它就超出了作用域,所以它符合GC的条件。我明白了,但我想这取决于上面代码段中的
…
隐藏了什么。。。如果某些代码(似乎)偶然地在某个特定Java实现上工作,而在另一个(例如OpenJDK)上不工作(严格地说是由不同的GC实现引起的),我仍然会觉得“奇怪”。。。作用域规则应该是相同的(如果不是,则会有更多问题:)@EJP感谢您的建议,我已经尝试将reg设置为静态类变量,而不是本地类变量(请参见编辑)-不幸的是,行为没有改变。在Ubuntu机器上,该方法仍然立即存在(现在使用Oracle Java运行)。@ChristopheD没有人说范围规则不同。当然不是。此代码在所有Java版本上都是错误的,除非“…”中存在休眠。