如何远程关闭 Java RMI 服务器

发布于 2024-07-07 14:43:13 字数 1994 浏览 8 评论 0原文

我有一个非常简单的 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

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

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

    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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听你说爱我 2024-07-14 14:43:13

如果有人遇到类似的问题,我自己找到了答案。 这是我的 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){}
}

In case anyone is having a similar problem, I figured out the answer myself. 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){}
}
顾北清歌寒 2024-07-14 14:43:13

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

Actually just unregistering and immediately calling System.exit doesn't shut down cleanly. It basically breaks the connection before informing the client that the message was completed. What works is to start a small thread that shuts down the system like:

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

The thread is needed to be able to let something happen in the future while still returning from the quit method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文