如何优雅地停止Java进程?
如何在 Linux 和 Windows 中优雅地停止 Java 进程?
什么时候被叫到,什么时候不被叫到?Runtime.getRuntime().addShutdownHook
那么终结者呢,它们在这里有帮助吗?
我可以从shell向Java进程发送某种信号吗?
我正在寻找更可取的便携式解决方案。
如何在 Linux 和 Windows 中优雅地停止 Java 进程?
什么时候被叫到,什么时候不被叫到?Runtime.getRuntime().addShutdownHook
那么终结者呢,它们在这里有帮助吗?
我可以从shell向Java进程发送某种信号吗?
我正在寻找更可取的便携式解决方案。
关闭挂钩在未强制终止 VM 的所有情况下执行。因此,如果您要发出“标准”杀戮(从杀戮命令),那么它们将执行。同样,它们将在调用 后执行。SIGTERM
System.exit(int)
然而,硬杀(或)然后他们不会执行。同样(显然),如果你从计算机中拔出电源,将其放入沸腾的熔岩桶中,或者用大锤将CPU打成碎片,它们也不会执行。不过,您可能已经知道这一点。kill -9
kill -SIGKILL
终结器确实也应该运行,但最好不要依赖它来清理关闭,而是依靠关闭钩子来干净利落地停止事情。而且,与往常一样,要小心死锁(我已经看到太多的关机钩子挂起了整个过程)!
好吧,在我选择使用“Java监视和管理”
的所有可能性之后,概述在这里
,它允许您以相对简单的方式从另一个应用程序控制一个应用程序。您可以从脚本中调用控制应用程序,以便在终止受控应用程序之前正常停止它。
下面是简化的代码:
受控应用程序:
使用 folowing 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();
}
}
}
就是这样。:-)