Search code examples
javarmi

Why is my RMI server dying after 20 hours


I have a problem with my RMI application. After about 20 hours (+/- a few hrs) clients can no longer connect. In the first 20 hours of the server's lifetime though I can make as many connections as I want. I suspected a problem with the RMI remote object being garbacge collected as there are no references pointing to it, but I can rule that out for 2 reasons:

  1. I forced the JVM running the server to do a GC using jconsole and clients can still connect
  2. I hold a reference to my server in the main method, which I do not exit and the RMI registry and the stub are members of my server class.

My server creates an RMI registry on port 1099 and gets exported as a UnicastRemoteObject on port 5099. When clients can no longer connect after 20 hours I get a java.rmi.ConnectException. To be clear the server's java process is still running and the registry (running within that process) still responding and returning a remote object. The exception is thrown when I call a remote method on the client side.

If I do "netstat -tulpn" on my server machine I can see that the java process is listening on port 5099 initially, but once that 20 hour bug kicks in the server is no longer listening on that port. I think I can rule out firewall issues as well, as I have disabled the server firewall for testing. Below is a simplified version of my code. Any ideas of what's going on there and how to make the server live indefintely would be much appreciated. Cheers!

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;
}



}

Solution

  • The loop in main() isn't the best way to prevent your objects being DGC'd and GC'd. Just make stub and registry static.