2

这是一个使用 RMI 的客户端/服务器应用程序。一旦服务器收到一个用于destroy() 的RMI 请求——我需要中止VM。我正在Runtime.getRuntime().halt(0)为此目的使用。但是在调用 halt() 之后,VM 仍然存在,我可以杀死它的唯一方法是Force Kill在 OSX 上使用。

调用线程的堆栈跟踪如下:

"RMI TCP Connection(3)-192.168.1.4" daemon prio=5 tid=7f99a7103000 nid=0x11d467000 runnable [11d464000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.Shutdown.halt0(Native Method)
    at java.lang.Shutdown.halt(Shutdown.java:95)
    - locked <7f44c90d0> (a java.lang.Shutdown$Lock)
    at java.lang.Runtime.halt(Runtime.java:256)
    at net.sourceforge.marathon.runtime.JavaRuntime.destroy(JavaRuntime.java:178)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at net.sourceforge.rmilite.impl.RemoteInvocationHandlerImpl.invoke(RemoteInvocationHandlerImpl.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)

可能是什么问题?

4

2 回答 2

2

我尝试了多种方法来完成这项工作。

  1. 添加Runtime#runFinalization在调用 halt() 之前
  2. 调用halt()SwingUtilities.invokeAndWait
  3. 调用halt()SwingUtilities.invokeLater

这些都不起作用。最后,

  1. halt()使用在计时器任务中调用Timer#schedule

这有效并且一直有效到现在。感谢大家的回复。

于 2012-12-27T07:34:24.570 回答
0

当您收到 destroy() 命令时,您应该:

  1. 取消导出所有远程对象。
  2. 取消导出任何注册表。
  3. 清除对远程对象和注册表的任何静态引用。

然后 JVM 将自动退出,除非您有任何非守护线程正在执行。

于 2015-09-03T10:17:04.393 回答