如何远程关闭Java RMI服务器

我有一个非常简单的Java RMI服务器,如下所示:

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."); } } 

当我调用exit方法时,System.exit(1)抛出以下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.(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 

我在这种方法中做错了什么?

如果有人遇到类似的问题,我自己想出了答案。 这是我的exit()方法:

 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){} } 

实际上只是取消注册并立即调用System.exit不会干净地关闭。 它通常在通知客户端消息已完成之前断开连接。 什么有效是启动一个关闭系统的小线程,如:

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

该线程需要能够在将来从quit方法返回时让某些事情发生。