2014-03-13 96 views
0

一个RMI服务器工作正常,没有stopServer功能。干净的方式来停止RMI服务器

public class HelloServer extends UnicastRemoteObject implements HelloInterface 
{ 
    private final static int PORT=1102; 
    private final String serverName="server"; 
    private Timer timer; 

    public HelloServer() throws RemoteException 
    { 
     timer = new Timer(); //At this line a new Thread will be created 
     timer.schedule(new StopServerTask(), 5000); 

    } 

    @Override 
    public String serverResponse(String request) throws RemoteException 
    { 
    return "Hello"+request; 
    } 


    public static void main(String[] args) 
    { 

     try 
     { 

      HelloServer skeleton=new HelloServer(); 
      System.out.println("Starting server"); 
      skeleton.startServer(); 
      System.out.println("Server started"); 


     } 
     catch (RemoteException ex) 
     { 
      ex.printStackTrace(); 
     } 


    } 

    public void startServer() 
    { 
    try { 

      HelloServer skeleton=new HelloServer(); 
      Registry reg=LocateRegistry.createRegistry(PORT); 
      reg.rebind(serverName, skeleton); 
      System.out.println("Server is ready"); 

     } catch (RemoteException ex) 
     { 
      Logger.getLogger(HelloInterface.class.getName()).log(Level.SEVERE, null, ex); 
     }  
    } 

    public void stopServer() 
    { 
    System.out.println("Stopping server"); 
     try { 

      Registry rmiRegistry = LocateRegistry.getRegistry(PORT); 
      HelloInterface myService = (HelloInterface) rmiRegistry.lookup(serverName); 

      rmiRegistry.unbind(serverName); 

      UnicastRemoteObject.unexportObject(rmiRegistry, true); 

     } catch (NoSuchObjectException e) 
     { 
      e.printStackTrace(); 
     } catch (NotBoundException e) 
     { 
      e.printStackTrace(); 
     } catch (RemoteException ex) { 
      Logger.getLogger(HelloServer.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    class StopServerTask extends TimerTask 
     { 

     @Override 
     public void run() 
     { 
     stopServer(); 
     } 

     } 
} 

每当stopServer()的调用的例外在

UnicastRemoteObject.unexportObject(rmiRegistry, true); 

这里被抛出的堆栈跟踪

java.rmi.NoSuchObjectException: object not exported 
    at sun.rmi.transport.ObjectTable.unexportObject(ObjectTable.java:153) 
    at java.rmi.server.UnicastRemoteObject.unexportObject(UnicastRemoteObject.java:297) 
    at rmi.HelloServer.stopServer(HelloServer.java:84) 

东西是相同的,甚至当我用

清洁服务对象
UnicastRemoteObject.unexportObject(myService, true); 

Cou有人建议一个干净的方式来停止服务器,这也释放端口供重用。

+1

可能的答案可在[终止Java RMI服务器应用程序](http://stackoverflow.com/questions/18782937/terminate-java-rmi-server-application) – Braj

回答

1

您需要存储LocateRegistry.createRegistry(),的结果并取出导出。目前你正试图取出一个存根。

0

我在我的rmi-server上实现了关机服务。如果我想关闭它,我用密码来调用它。简单的例子:

public interface ShutdownInterface extends Remote { 
    public void shutdownService(String password) throws RemoteException; 
} 

的服务器端实现可以是这个样子:

public class ShutdownService extends UnicastRemoteObject implements ShutdownInterface { 

private static final long serialVersionUID = 1L; 

private boolean doShutdown = false; 

public ShutdownService() throws RemoteException { 
    super(); 
} 

@Override 
public void shutdownService(String password) throws RemoteException { 
    if ("abcde12345".equals(password)) { 
     System.out.println("shutdown requested."); 
     this.doShutdown = true; 
    } else { 
     System.out.println("wrong pwd for shutdown"); 
    } 

} 

public boolean isDoShutdown() { 
    return this.doShutdown; 
} 

}

现在,服务器本身保持这一基准:

public class BackendServer { 
public final static int RMI_PORT = 1974; 
private Registry registry = null; 
private ShutdownService shutdownService = null; 

public BackendServer() throws RemoteException { 
    registry = LocateRegistry.createRegistry(RMI_PORT); 
    this.shutdownService = new ShutdownService(); 
} 

public void initialize() throws AccessException, RemoteException, AlreadyBoundException { 
    shutdownService = new ShutdownService(); 
    registry.bind("ShutdownService", shutdownService); 
    registry.bind("MyDataService", new MyDataService()); 
} 

public void stop() throws NoSuchObjectException { 
    System.out.println("stopping rmi server."); 
    UnicastRemoteObject.unexportObject(registry, true); 
    System.exit(0); 
} 

public boolean shouldStop() { 
    return this.shutdownService.isDoShutdown(); 
} 

public static void main(String args[]) { 
    try { 
     BackendServer bs = new BackendServer(); 
     bs.initialize(); 
     System.out.println("Server ready."); 

     while (!bs.shouldStop()) { 
      Thread.sleep(1000); 
     } 
     bs.stop(); 
    } catch (Exception e) { 
     System.err.println("Server exception: " + e.toString()); 
     e.printStackTrace(); 
    } 
} 

}

当然,这可以用更美丽的方式来实现,但是这应该让您了解如何轻松实现关机。您可以从主客户端或您为服务器编码的小型命令行工具调用它。