如何优雅地停止java进程?

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

Runtime.getRuntime().addShutdownHook何时被调用,什么时候不调用?

终结者怎么样,他们在这里帮助吗?

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

我在寻找最好的便携式解决方案。

回答:

关闭挂钩在虚拟机未被强行杀死的所有情况下执行。因此,如果您要发出“标准”杀死(kill命令中的SIGTERM),那么它们将执行。同样,他们将在致电System.exit(int)后执行。

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

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

回答:

相似问题Here

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

shutdownHook只会在VM关闭时被调用。我认为它可以做你想做的事。

回答:

在关机的情况下,您是否阅读过javadoc?在Linux中

https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-

回答:

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

便携信令可以通过在您的Java应用程序中集成SocketServer。这并不困难,并让您自由发送任何您想要的命令。

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

回答:

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

回答:

好吧,毕竟我已经选择与“Java监视和管理”
Overview is here
这允许你从另外一个相对简单的方式控制一个应用程序的工作准备。您可以从脚本中调用控制应用程序,以便在杀死它之前正常停止受控应用程序。

这里是简化的代码:

受控应用:
与如下因素VM参数运行:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote .port = 9999
-Dcom.sun.management.jmxremote.authenticate =假
-Dcom.sun.management.jmxremote.ssl =假

//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并等待一个信息到达它。例如一个带有“魔术”字符的字符串:)然后做出关闭:System.exit()的反应。您可以使用外部应用程序(如telnet)将这些信息发送到socke。

回答:

这是一个有点棘手,但便携的解决方案:

  • 在您的应用程序当你想正常关闭您的JVM,安装Java Agent调用System.exit实施关闭挂钩
  • ( )使用Attach API。

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

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

以上是 如何优雅地停止java进程? 的全部内容, 来源链接: utcz.com/qa/258230.html

回到顶部