Java 停止RMI服务器的干净方法

Java 停止RMI服务器的干净方法,java,rmi,Java,Rmi,一个RMI服务器,在没有stopServer功能的情况下工作正常 public class HelloServer extends UnicastRemoteObject implements HelloInterface { private final static int PORT=1102; private final String serverName="server"; private Timer timer; public HelloServer(

一个RMI服务器,在没有stopServer功能的情况下工作正常

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

是否有人可以建议一种干净的方法来停止服务器,同时释放端口以供重用。

您需要存储
LocateRegistry.createRegistry(),
的结果并取消该端口的导出。目前您正在尝试取消导出存根。

我在rmi服务器中实现了关闭服务。如果我想关闭它,我会用密码打电话给它。简单的例子:

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

当然,这可以用一种更漂亮的方式实现,但这应该让您了解如何轻松地自己实现关机。您可以从主客户端或为服务器编写的小命令行工具调用它。

可能的答案可从