How to remotely shut down a Java RMI server

I have a very simple Java RMI Server that looks like this:

import java.rmi.*; import java.rmi.server.*; public class CalculatorImpl extends UnicastRemoteObject implements Calculator { private String mServerName; public CalculatorImpl(String serverName) throws RemoteException { super(); mServerName = serverName; } public int calculate(int op1, int op2) throws RemoteException { return op1 + op2; } public void exit() throws RemoteException { try{ Naming.unbind(mServerName); System.out.println("CalculatorServer exiting."); } catch(Exception e){} System.exit(1); } public static void main(String args[]) throws Exception { System.out.println("Initializing CalculatorServer."); String serverObjName = "rmi://localhost/Calculator"; Calculator calc = new CalculatorImpl(serverObjName); Naming.rebind(serverObjName, calc); System.out.println("CalculatorServer running."); } } 

When I call the exit method, System.exit (1) throws the following exception:

 CalculatorServer exiting. java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is: java.io.EOFException at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at CalculatorImpl_Stub.exit(Unknown Source) at CalculatorClient.<init>(CalculatorClient.java:17) at CalculatorClient.main(CalculatorClient.java:29) Caused by: java.io.EOFException at java.io.DataInputStream.readByte(DataInputStream.java:243) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:189) ... 4 more [2]+ Exit 1 java CalculatorImpl 

What am I doing wrong in this method?

+7
java rmi
source share
2 answers

In case someone faces a similar problem, I myself figured out the answer. Here is my exit () method:

 public void exit() throws RemoteException { try{ // Unregister ourself Naming.unbind(mServerName); // Unexport; this will also remove us from the RMI runtime UnicastRemoteObject.unexportObject(this, true); System.out.println("CalculatorServer exiting."); } catch(Exception e){} } 
+15
source share

Actually, only an unregistered and immediately calling System.exit does not close cleanly. This basically terminates the connection before informing the client that the message was completed. What works is to start a small thread that shuts down the system, for example:

 public void quit() throws RemoteException { System.out.println("quit"); Registry registry = LocateRegistry.getRegistry(); try { registry.unbind(_SERVICENAME); UnicastRemoteObject.unexportObject(this, false); } catch (NotBoundException e) { throw new RemoteException("Could not unregister service, quiting anyway", e); } new Thread() { @Override public void run() { System.out.print("Shutting down..."); try { sleep(2000); } catch (InterruptedException e) { // I don't care } System.out.println("done"); System.exit(0); } }.start(); } 

This thread is needed to allow something to happen in the future, still returning from the quit method.

+4
source share

All Articles