RMI Server不会使用LocateRegistry.createRegistry方法进行线程化和死亡

时间:2011-11-07 21:10:25

标签: java rmi

我现在使用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服务器启动并突然死亡。怎么

3 个答案:

答案 0 :(得分:8)

  

我期待LocateRegistry代码创建一个线程

这不是那么简单。

  1. 在新端口上导出第一个对象会创建一个侦听该端口的线程,并且取消导出侦听端口的最后一个对象会导致该线程退出。这适用于所有远程对象,而不仅仅是本地Registry对象。

  2. 可以通过本地GC自动进行取消导出,然后可以通过远程DGC触发。

  3. 您的JVM退出是因为您没有将LocateRegistry.createRegistry()返回的值保存在静态变量中,因此它得到了GC,因此对象未被导出,因此没有在端口1099上导出远程对象,所以侦听1099的线程退出,所以没有非守护进程线程,所以JVM退出。

    解决方案:将LocateRegistry.createRegistry()的结果存储在静态变量中。当您希望JVM退出时,可以使用它来取消导出注册表。

答案 1 :(得分:4)

启动RMI注册表有两种可能的方法。

  1. LocateRegistry.createRegistry(1099);执行注册表的java应用程序不能完成。在你的情况下,你可以开始一个新的“永无止境”的线程(见下面的源代码)
  2. rmiregistry这是一个包含在启动RMI注册服务的java发行版中的工具。见rmiregistry - The Java Remote Object Registry
  3. 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()方法。
  • 创建一些非守护程序线程。当然,只有当线程实际上做了一些有用的事情而不是阻止JVM退出时才这样做。