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