如何优雅地停止java进程?
如何在Linux和Windows中优雅地停止Java进程 何时调用如何优雅地停止java进程?,java,linux,windows,shell,process,Java,Linux,Windows,Shell,Process,如何在Linux和Windows中优雅地停止Java进程 何时调用Runtime.getRuntime().addShutdownHook,何时不调用 终结器呢,它们在这里有帮助吗 我可以从shell向Java进程发送某种信号吗 我正在寻找最好的便携式解决方案。类似问题 Java中的终结器不好。它们为垃圾收集增加了大量开销。尽可能避免它们 只有在VM关闭时才会调用shutdownHook。我认为它可以很好地满足您的需要。Linux中的信号发送可以通过“kill”(可用信号的mankill)完成,
Runtime.getRuntime().addShutdownHook
,何时不调用
终结器呢,它们在这里有帮助吗
我可以从shell向Java进程发送某种信号吗
我正在寻找最好的便携式解决方案。类似问题
Java中的终结器不好。它们为垃圾收集增加了大量开销。尽可能避免它们
只有在VM关闭时才会调用shutdownHook。我认为它可以很好地满足您的需要。Linux中的信号发送可以通过“kill”(可用信号的mankill)完成,您需要进程ID来完成。(ps ax | grep java)或类似的东西,或者在创建进程时存储进程id(这在大多数linux启动文件中使用,请参阅/etc/init.d) 通过在java应用程序中集成SocketServer,可以实现便携式信令。这并不难,它让你可以自由地发出任何你想要的命令 如果您是指finally子句而不是finalizer;当调用System.exit()时,它们不会被执行。
终结器应该可以工作,但除了打印调试语句之外,不应该真正做任何更重要的事情。它们是危险的。关闭钩子在VM未被强制杀死的所有情况下都会执行。因此,如果您要发出一个“标准”kill(
SIGTERM
来自kill命令),那么它们将执行。类似地,它们将在调用System.exit(int)
后执行
但是,硬杀伤(kill-9
或kill-SIGKILL
)则不会执行。类似地(而且很明显),如果你从计算机中拔出电源,将其放入沸腾的熔岩缸中,或者用大锤将CPU敲碎,它们也不会执行。不过,你可能已经知道了
终结器也应该运行,但最好不要依赖于它来进行关机清理,而是依赖于您的关机挂钩来干净地停止事情。而且,一如既往,要小心死锁(我已经看到太多的关机挂钩挂起了整个过程) 谢谢你的回答。就像我的情况一样。 但我也碰到了一个叫做监视和管理bean的东西:
这为远程监控和操纵java进程提供了一些很好的可能性。(在Java 5中引入)好的,在我选择使用“Java监视和管理”的所有可能性之后,
这使您可以相对轻松地从另一个应用程序控制一个应用程序。您可以从脚本中调用控制应用程序,以便在终止控制应用程序之前优雅地停止它。
以下是简化代码: 受控应用程序:
使用以下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");
}
}
}
控制应用程序:使用stop或start作为命令行参数运行它
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,等待信息到达。例如,一个带有“魔术”字的字符串:),然后做出反应使shutdown:System.exit()。您可以使用外部应用程序(如telnet)将此类信息发送到Sock。这里有一个有点棘手但可移植的解决方案:
- 在应用程序中,实现一个关闭挂钩
- 当您想要优雅地关闭JVM时,请安装一个调用System.exit()的
有关解决方案的详细说明可在此处找到:您应该真正定义“优雅”的含义。(请)我猜他们的意思是,他们希望在程序被终止之前,有机会清理资源、释放、锁定并刷新磁盘上的任何持久数据。所以在所有情况下都会调用shutdownHook?如果从shell中“杀死”进程会怎么样?好吧,如果你给它一个kill-9:)不幸的是,这在Windows7(64位)上似乎不起作用。我尝试使用taskill,但没有force标志,遇到以下错误:“错误:无法终止PID 14324的进程。原因:此进程只能强制终止(使用/F选项)。“提供force选项“/F”,显然会立即关闭进程。您不能依赖正在运行的终结器。