2008-10-27 17 views
7

Tengo una muy simple servidor RMI de Java que se parece a lo siguiente:Cómo remotamente el cierre de un servidor 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."); 
     } 
} 

Cuando llamo el método de salida, System.exit (1) desencadena 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?

Respuesta

15

En caso de que alguien tenga un problema similar, yo mismo descubrí la respuesta. Aquí está mi salida método():

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

Gracias por el ejemplo de unexportObject. –

4

En realidad simplemente anula el registro y llamar inmediatamente System.exit no cerró correctamente. Básicamente rompe la conexión antes de informar al cliente que el mensaje se completó. Lo que funciona es para iniciar un pequeño hilo que se 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(); 
} 

Se necesita el hilo para ser capaz de dejar que algo suceda en el futuro, al tiempo que volvía de la método de dejar de fumar.

+3

Toda la parte del subproceso es una buena idea, pero no es necesaria. Solo tiene que establecer UnicastRemoteObject.unexportObject (esto, verdadero) en lugar de UnicastRemoteObject.unexportObject (esto, falso). Acabo de intentar el mismo problema. – Anonymous

+0

Tuve el mismo problema y configurar el segundo parámetro de unexportObject no fue de ayuda, pero ejecutar System.exit en un Thread ayudó. – simon

Cuestiones relacionadas