I have set up a client/server project using Java RMI. Below I show parts of the implementation. I launch the server using
ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", "start /B java -jar myServer.jar --start);
this.myProcess = processBuilder.start();
I have added a main method to the server which handles the command line call. The server starts and runs perfectly. The client is able to connect and perform as I expect it to.
My problems arise when I try to kill the server. This needs to be done from outside. The object which previously started the process is not available anymore. To actually stop the server, the main method of the server class calls a stop method (see below). This method now kills the RMI but it does not the least stop the JVM from running. The process is still available and needs to be killed from the task manager (on Windows).
Do I miss some fact in my implementation that yields this behavior. Why does the process not stop running?
public class MyServer {
// ...
public void startServer() throws RemoteException {
// the RMI registry
Registry registry;
try {
// find the registry
registry = LocateRegistry.createRegistry(portRMI);
} catch (Exception e) {
// if the registry does not yet exist, try to create a new registry
// entry or use an existing one
registry = LocateRegistry.getRegistry(MyConstants.HOST_NAME, portRMI);
}
// create the object
servantObject = new MyServant();
// bind the object to the server
registry.rebind(MyConstants.SERVER_NAME, servantObject);
}
public void stopServer() throws RemoteException {
try {
// access the service
Registry rmiRegistry = LocateRegistry.getRegistry(MyConstants.HOST_NAME, portRMI);
MyService myService = (MyService) rmiRegistry.lookup(MyConstants.SERVER_NAME);
rmiRegistry.unbind(MyConstants.SERVER_NAME);
// get rid of the service object
UnicastRemoteObject.unexportObject(myService, true);
// get rid of the rmi registry
UnicastRemoteObject.unexportObject(rmiRegistry, true);
} catch (NoSuchObjectException e) {
// ...
} catch (NotBoundException e) {
// ...
}
}
public static void main(String[] args) {
// handle arguments and call either startServer or stopServer
}
}
public class MyServant extends UnicastRemoteObject implements MyService {
// ...
}
public interface MyService extends Remote {
// ...
}
You should add a self writtem RMIService interface available in your RMIServer so that a program that wishes to stop the running server instructs it to stop.
Your app that tries to stop the server just unbinds some object, as it is not the running rmi server process itself it will not have a big effect.
if your rmi sever is process a, you should write an app (using rmi) running as process b to send a message to process a to stop it.