我得到以下异常,我无法弄清楚为什么会发生。RMI; JRMP连接错误;由连接重置导致
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
我有一个守护程序类负责在单独的JVM中启动服务器。在那个守护进程中,我有一个ShutDownHook,它调用远程服务器对象上的一个方法,在服务器上启动一个关闭过程。
守护程序本身也是一个导出的RMI对象,但在不同的端口上,以便我可以远程启动服务器。 这意味着守护进程创建了一个注册表监听端口1099,服务器有一个注册监听1098后。
现在我也有一个“ClientGui”,可以关闭服务器并重新启动它。它可以访问Daemon以启动服务器,并通过服务器将其关闭。
守护类:
//.....
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();
}
}
}
}
从我ClientGui我访问远程服务器对象完全相同的方式从后台程序,也可以调用killServer()方法没有问题。但是当我按CTRL + C从守护进程启动ShutDownHook时,当试图查找导出的服务器对象时,会引发上述异常。
的网络搜索没有给我就如何解决这个任何想法......但也许我找错了方向......
任何帮助是极大的赞赏,我感谢任何人提前! :)
我得到关闭JVM杀死注册表,但在这种情况下,我不查找它本身,但导出的服务器对象。服务器在由守护程序启动的单独JVM中运行。我认为问题实际上是我的守护进程从“cmd.exe”开始,并且从守护进程内启动的服务器也使用与守护进程相同的窗口。因此点击“CTRL + C”会关闭这两个JVM。由于服务器没有任何挂钩,我猜服务器注册表在Daemon可以访问它之前就关闭了。并且由于getRegistry不检查它是否存在会解释该行的异常。谢谢:) – motaa
啊OK错过了。我会在同一个JVM中运行'Server',这将消除所有的malarkey。如果您必须在两个JVM中执行此操作,则应该通过'this.reg'在shutdown hook中查找,而不是通过'LocateRegistry.getRegistry()'查找。原因是'this.reg'是实际的Registry实现对象,而不是存根,所以即使它已被取消导出或其I/O线程已退出,查找仍然有效。 – EJP
我看到你的观点@EJP,但服务器必须有它自己的JVM来接受更改。使用'this.reg'我会参考。 JVM的守护程序(1)。这个想法是在JVM(2)中获取服务器的reg,查找服务器对象并启动关闭,立即返回并让Daemon完成。我发现我可以将服务器对象注册到守护进程,因此我只需要处理一个。但是如果我在服务器上失去了守护进程钩子,我会有一个僵尸进程。不过,我在开始使用新服务器时会处理这个问题。使用服务器注册我一直控制着来自我的GUI的“僵尸服务器”。 :) – motaa