我现在使用LocateRegistry.createRegistry(1099)
而不是在外部进程中使用注册表。但是,在主程序结束后,注册表将会死亡。例如,如果我创建一个创建注册表的简单程序,它将无法工作,因为在main executino之后代码结束。我期待LocateRegistry
代码创建一个线程,但似乎并非如此。这是使用LocateRegistry
的正常行为还是我遗漏了什么?
代码示例:
// ommited imports
public class RMITest {
public static void main(String[] args) {
LocateRegistry.createRegistry(1099);
// JVM will exit now!!!
}
}
RMI服务器启动并突然死亡。怎么
答案 0 :(得分:8)
我期待LocateRegistry代码创建一个线程
这不是那么简单。
在新端口上导出第一个对象会创建一个侦听该端口的线程,并且取消导出侦听端口的最后一个对象会导致该线程退出。这适用于所有远程对象,而不仅仅是本地Registry对象。
可以通过本地GC自动进行取消导出,然后可以通过远程DGC触发。
您的JVM退出是因为您没有将LocateRegistry.createRegistry()
返回的值保存在静态变量中,因此它得到了GC,因此对象未被导出,因此没有在端口1099上导出远程对象,所以侦听1099的线程退出,所以没有非守护进程线程,所以JVM退出。
解决方案:将LocateRegistry.createRegistry()
的结果存储在静态变量中。当您希望JVM退出时,可以使用它来取消导出注册表。
答案 1 :(得分:4)
启动RMI注册表有两种可能的方法。
LocateRegistry.createRegistry(1099);
执行注册表的java应用程序不能完成。在你的情况下,你可以开始一个新的“永无止境”的线程(见下面的源代码)rmiregistry
这是一个包含在启动RMI注册服务的java发行版中的工具。见rmiregistry - The Java Remote Object Registry RMI注册服务器的示例代码。
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RmiTest {
public static void main(String[] args) throws IOException {
final Object monitor = new Object();
new Thread(new Runnable() {
public void run() {
try {
LocateRegistry.createRegistry(1099);
synchronized (monitor) {
monitor.wait();
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RMI Registry Thread finished.");
}
}, "RMI Registry Thread").start();
System.out.println("Press enter to exit...");
System.in.read();
synchronized (monitor) {
monitor.notify();
}
}
}
答案 2 :(得分:0)
LocateRegistry.createRegistry(1099);
在我的计算机上创建一个名为RMI TCP Accept-1099
的新守护程序线程。该线程基本上在1099上侦听新的TCP / IP连接。
当JVM退出时,守护程序线程会自动终止。在您的情况下,当您离开main()
方法时JVM退出。更确切地说 - 当没有更多的非守护程序线程时它会退出 - 显然你的应用程序中只有一个非守护程序线程(名为main
)。
所以你有两个选择:
main()
来完成sleep()
方法。