如何优雅地停止java进程?

如何在Linux和Windows中优雅地停止Java进程?

什么时候Runtime.getRuntime().addShutdownHook被调用,什么时候没有?

终结者呢,他们在这里帮助吗?

我可以从shell发送某种信号给Java进程吗?

我正在寻找最好的便携式解决scheme。

closures挂钩在虚拟机不被强行杀死的所有情况下执行。 所以,如果你要发出一个“标准”kill(kill命令中的SIGTERM ),那么他们将执行。 同样,它们将在调用System.exit(int)之后执行。

不过杀死一个( kill -9kill -SIGKILL ),那么他们将不会执行。 同样地(显然),如果你从计算机中取出电源,将它放入沸腾的熔岩缸中,或者用大锤击碎CPU,它们将不会执行。 不过,你可能已经知道了。

终结器真的应该运行,但最好不要依靠closures清理,而是依靠你的closures钩子干净地停止事情。 和往常一样,要小心死锁(我已经看到太多closures挂钩挂起整个过程)!

好吧,毕竟我select与“Java监控和pipe理”
概述在这里
这允许您以相对简单的方式从另一个应用程序控制一个应用程序。 您可以通过脚本调用控制应用程序,以便在控制应用程序停止前正常停止。

这是简化的代码:

受控应用程序:
使用以下VM参数运行它:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port = 9999
-Dcom.sun.management.jmxremote.authenticate = FALSE
-Dcom.sun.management.jmxremote.ssl = FALSE

 //ThreadMonitorMBean.java public interface ThreadMonitorMBean { String getName(); void start(); void stop(); boolean isRunning(); } // ThreadMonitor.java public class ThreadMonitor implements ThreadMonitorMBean { private Thread m_thrd = null; public ThreadMonitor(Thread thrd) { m_thrd = thrd; } @Override public String getName() { return "JMX Controlled App"; } @Override public void start() { // TODO: start application here System.out.println("remote start called"); } @Override public void stop() { // TODO: stop application here System.out.println("remote stop called"); m_thrd.interrupt(); } public boolean isRunning() { return Thread.currentThread().isAlive(); } public static void main(String[] args) { try { System.out.println("JMX started"); ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread()); MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("com.example:type=ThreadMonitor"); server.registerMBean(monitor, name); while(!Thread.interrupted()) { // loop until interrupted System.out.println("."); try { Thread.sleep(1000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } } } catch(Exception e) { e.printStackTrace(); } finally { // TODO: some final clean up could be here also System.out.println("JMX stopped"); } } } 

控制应用程序:
运行它停止或作为命令行参数启动

 public class ThreadMonitorConsole { public static void main(String[] args) { try { // connecting to JMX System.out.println("Connect to JMX service."); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); // Construct proxy for the the MBean object ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor"); ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true); System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running"); // parse command line arguments if(args[0].equalsIgnoreCase("start")) { System.out.println("Invoke \"start\" method"); mbeanProxy.start(); } else if(args[0].equalsIgnoreCase("stop")) { System.out.println("Invoke \"stop\" method"); mbeanProxy.stop(); } // clean up and exit jmxc.close(); System.out.println("Done."); } catch(Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

而已。 🙂

另一种方式:您的应用程序可以打开一个服务器socet并等待一个信息到达它。 例如一个带有“魔术”字符的string:)然后作出closures:System.exit()。 您可以使用外部应用程序(如telnet)将这些信息发送到socke。

类似的问题这里

Java中的终结器是不好的。 他们为垃圾收集增加了很多开销。 尽可能避免使用它们。

shutdownHook只会在VMclosures时被调用。 我觉得很好,可以做你想做的事情。

这是一个有点棘手,但便携式解决scheme:

  • 在你的应用程序中实现closures挂钩
  • 如果要closuresJVM,请安装使用Attach API调用System.exit()的Java代理 。

我实现了Java代理。 它在Github上可用: https : //github.com/everit-org/javaagent-shutdown

有关解决scheme的详细说明,请访问: https : //everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/

Linux中的信号传输可以用“kill”来完成(man kill为可用的信号),你需要进程ID来做到这一点。 (ps ax | grep java)或类似的东西,或者当进程被创build时存储进程id(这在大多数linux启动文件中使用,参见/etc/init.d)

便携式信令可以通过在你的Java应用中集成一个SocketServer来完成。 这并不难,让你自由发送任何你想要的命令。

如果你的意思是最终条款而不是终结者; System.exit()被调用时,它们不会被扩展。 终结器应该工作,但不应该做任何更重要的事情,但打印debugging声明。 他们很危险

谢谢你的答案。 关机钩接缝就像在我的情况下工作。 但是我也碰到了一个叫做Monitoring and Management beans的东西:
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
这给了一些很好的可能性,用于远程监视和操作java进程。 (在Java 5中引入)