Pregunta

Tengo un servidor Java RMI muy simple que se parece a lo siguiente:

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

Cuando llamo al método de salida, System.exit (1) lanza la siguiente excepción:

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

¿Qué estoy haciendo mal en este método?

¿Fue útil?

Solución

En caso de que alguien tenga un problema similar, yo mismo me di cuenta de la respuesta. Aquí está mi método 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){}
}

Otros consejos

En realidad, simplemente anular el registro y llamar inmediatamente a System.exit no se cierra correctamente. Básicamente, se rompe la conexión antes de informar al cliente que el mensaje se completó. Lo que funciona es iniciar un pequeño hilo que apaga el sistema como:

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

El hilo es necesario para permitir que algo suceda en el futuro mientras aún regresa del método para dejar de fumar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top