为什么我的RMI服务器在20小时后死亡

时间:2013-07-22 08:52:56

标签: java rmi

我的RMI应用程序出了问题。大约20个小时(+/-几个小时)后,客户端无法再连接。在服务器生命周期的前20个小时内,尽管我可以根据需要创建尽可能多的连接。我怀疑RMI远程对象是收集garbacge的问题,因为没有引用指向它,但我可以排除这有两个原因:

  1. 我强制运行服务器的JVM使用jconsole执行GC,客户端仍然可以连接
  2. 我在main方法中保存了对我的服务器的引用,我没有退出,RMI注册表和存根是我服务器类的成员。
  3. 我的服务器在端口1099上创建一个RMI注册表,并在端口5099上作为UnicastRemoteObject导出。当客户端在20小时后无法再连接时,我得到一个java.rmi.ConnectException。要清楚,服务器的java进程仍在运行,并且注册表(在该进程中运行)仍然响应并返回远程对象。当我在客户端调用远程方法时抛出异常。

    如果我在我的服务器机器上执行“netstat -tulpn”,我可以看到java进程最初正在侦听端口5099,但是一旦服务器中的那个20小时错误消失,就不再监听该端口了。我想我也可以排除防火墙问题,因为我已经禁用了服务器防火墙进行测试。下面是我的代码的简化版本。任何关于那里发生的事情以及如何使服务器无限期生活的想法将不胜感激。干杯!

    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    import java.rmi.server.UnicastRemoteObject;
    
    public class MyRMIServer implements MyRMIInterface {
    
    private MyRMIInterface stub;
    
    private Registry registry;
    
    
    public static void main(String[] args) 
    {
        MyRMIServer server = new MyRMIServer(); 
        server.startRmiServices();
    
        // now sleep, don't let the main thread die, otherwise we might loose our ref to the 
    
        // RMI stub and/or registry
        while (true) 
        {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    private void startRmiServices()
    {
    
        try {
            // set up security manager
            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new SecurityManager());
            }
    
            // create stub
            stub = (MyRMIInterface) UnicastRemoteObject.exportObject(this,5099);
    
            // Bind the remote object's stub in the registry
            registry = LocateRegistry.createRegistry(1099);
            registry.rebind("MyServer", stub);
    
            System.out.println("RMI ready");
    
        } catch (RemoteException e) {
            e.printStackTrace();
        } 
    }
    
    @Override
    public synchronized int remoteCall(int x) throws RemoteException
    {
        return x+1;
    }
    
    
    
    }
    

1 个答案:

答案 0 :(得分:1)

main()中的循环不是阻止对象进行DGC和GC的最佳方法。只需将stubregistry设为静态。