Search code examples
rmijrmp

RMI; JRMP connection error; Caused by connection reset


I get the following Exception and I can't figure out why that is happening.

java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: java.net.SocketException: Connection reset
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
at sun.rmi.server.UnicastRef.newCall(Unknown Source)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at Daemon$ShutDownProcedure.run(Daemon.java:126)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.DataInputStream.readByte(Unknown Source)
... 5 more

I have a Daemon class that is responsible to start up a Server in a separate JVM. In that Daemon I have a ShutDownHook that calls a method on the remote server object which, on the server, starts a shutdown procedure.

The Daemon itself is also an exported RMI object but on a different port so that I can start a server remotely. That means the Daemon has created a Registry listening on port 1099 and the Server has a Registry listening on post 1098.

Now I also have a "ClientGui" that can shutdown a server and restart it. It can access both the Daemon to launch a server and the Server to shut it down.

Daemon class:

//.....
private Daemon(String[] args){
    try {
        this.reg = LocateRegistry.createRegistry(1099);
        this.stub = (DaemonRemote) UnicastRemoteObject.exportObject(this, 1099);
        this.reg.rebind(DaemonRemote.class.getName(), this.stub);   
        this.arguments = args;
        Runtime.getRuntime().addShutdownHook(new ShutDownProcedure());          
    } catch (RemoteException e) {
        e.printStackTrace();
    }       
}

//....
public static void main(String[] args){             

  String initialargs = Arrays.stream(args).collect(Collectors.joining(" "));
  String[] command = new String[] {"java", "-Xmx4g","-cp", System.getProperty("java.class.path", "."), Server.class.getName(),initialargs};

  try {
    p = new ProcessBuilder(command).inheritIO().redirectErrorStream(true).start();          
    } catch (Exception e) {
      e.printStackTrace();  
    }       
    if(daemon == null)
        daemon = new Daemon(args);
}
//....
private class ShutDownProcedure extends Thread {

    @Override
    public void run(){      

        if(p.isAlive()){
          try {
            Registry serverreg = LocateRegistry.getRegistry(null, 1098);
            ServerRemote serverrmi = (ServerRemote) serverreg.lookup(ServerRemote.class.getName()); //this is the line where the exception occurs...
            serverrmi.killServer();
          } catch (IOException | NotBoundException | InterruptedException e) {          
            e.printStackTrace();
        }
    }
}

}

From my ClientGui I access the remote Server object in exactly the same way as from the Daemon and can also call the killServer() method without a problem. But when I hit CTRL+C to initiate the ShutDownHook from the Daemon, the mentioned exception is being thrown when trying to lookup the exported Server object.

The websearch didn't give me any ideas on how to solve this... but maybe I am looking in the wrong direction...

Any help is greatly appreciated and I thank anyone in advance! :)


Solution

  • As already stated in the comments, hitting "CTRL+C" during the batch-job (the Daemon is being started from cmd executing a bat-file) shuts down both JVM's and thus the registry created in the server JVM shuts down as well.

    To resolve my issue I just added a ShutDownHook to the server which will initiate its own ShutDownProcedure. Unfortunately I haven't found a good way to start a completely separate "unhidden" cmd-window and start another jar-application using ProcessBuilder yet.

    Thanks to EJP's advice, I removed the Registry creation part from the code and start it from the batch-file.