如何远程关闭Java RMI服务器

如何远程关闭Java RMI服务器,java,rmi,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

我有一个非常简单的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)抛出以下异常:

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
计算器服务器正在退出。
java.rmi.UnmarshaleException:错误解组返回头;嵌套异常是:
java.io.EOFException
位于sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203)
位于sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126)
在CalculatorImpl_存根退出时(未知源)
在CalculatorClient。(CalculatorClient.java:17)
位于CalculatorClient.main(CalculatorClient.java:29)
原因:java.io.EOFException
位于java.io.DataInputStream.readByte(DataInputStream.java:243)
位于sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:189)
... 4更多
[2] +退出1 java CalculatorImpl

这种方法有什么不对?

如果有人有类似的问题,我会自己找出答案。下面是我的exit()方法:


实际上,只是注销并立即调用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方法返回。

感谢unexportObject示例。整个线程部分是一个不错的主意,但不是必需的。您只需设置UnicastRemoteObject.unexportObject(此,true)而不是UnicastRemoteObject.unexportObject(此,false)。我只是尝试了同样的问题。我遇到了同样的问题,设置unexportObject的第二个参数没有帮助,但是在线程中运行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();
}