Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优雅地停止java进程?_Java_Linux_Windows_Shell_Process - Fatal编程技术网

如何优雅地停止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)完成,

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

何时调用
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()的
我实现了Java代理。可在Github上获得:


有关解决方案的详细说明可在此处找到:

您应该真正定义“优雅”的含义。(请)我猜他们的意思是,他们希望在程序被终止之前,有机会清理资源、释放、锁定并刷新磁盘上的任何持久数据。所以在所有情况下都会调用shutdownHook?如果从shell中“杀死”进程会怎么样?好吧,如果你给它一个kill-9:)不幸的是,这在Windows7(64位)上似乎不起作用。我尝试使用taskill,但没有force标志,遇到以下错误:“错误:无法终止PID 14324的进程。原因:此进程只能强制终止(使用/F选项)。“提供force选项“/F”,显然会立即关闭进程。您不能依赖正在运行的终结器。