&引用;“杀死进程树”;在windows上使用Java

&引用;“杀死进程树”;在windows上使用Java,java,apache-commons-exec,Java,Apache Commons Exec,我有一个Java webstart进程,它是windows批处理脚本的一部分。在本例中,我在批处理脚本中使用javaws命令。 这个匹配脚本(start.bat)是使用“ApacheCommonsExec”以编程方式调用的。在某些情况下,javaws调用的java进程挂起,我必须从批处理脚本start.bat开始终止整个进程线程。 有没有一种编程方式可以通过ApacheCommonsExec杀死整个进程树 我尝试在“start.bat”脚本中使用“execWatchdog.destroyProc

我有一个Java webstart进程,它是windows批处理脚本的一部分。在本例中,我在批处理脚本中使用javaws命令。 这个匹配脚本(start.bat)是使用“ApacheCommonsExec”以编程方式调用的。在某些情况下,javaws调用的java进程挂起,我必须从批处理脚本start.bat开始终止整个进程线程。 有没有一种编程方式可以通过ApacheCommonsExec杀死整个进程树

我尝试在“start.bat”脚本中使用“execWatchdog.destroyProcess();”。但是,它只终止start.bat进程,而不是整个进程树

有没有办法通过ApacheCommonsExec或类似的代码杀死整个进程树


<>我看到这个问题在C++中执行了一个等价的任务。我想知道是否有人实现了通过JNI调用windows本机系统调用

据我所知,commons exec中没有这样的选项。甚至不可能获得刚刚启动的任何进程的PID。您可以
trap
bash脚本中的kill信号,并在脚本进程被终止时让处理程序终止子进程。

最终获得了一些可行的方法,尽管这是一种迂回的方法 Apache Commons Exec API包含返回java.lang.Process对象的CommandLauncher类。多亏了

下面是从java.lang.Process获取windows进程Id的步骤。这使用了JNA库

最后是进程Id,这里是终止进程树的命令字符串
//字符串killCmd=“taskkill/F/T/PID”+JNAHandler.getPid(进程)

不幸的是,正如您所发现的,没有一种纯Java的方法可以做到这一点。您必须求助于本机命令或JNI库,它们都依赖于平台,比纯Java解决方案更复杂

值得一提的是,Java bug数据库中的相关bug:

幸运的是,我们可以说服Java开发人员,对于Java 8来说,子流程的糟糕处理是值得修复的。

Java版本9以后, Java提供了一种可以查询和终止主进程及其子进程的特性。 用于查询子进程的代码段

import java.io.IOException;

public class ProcessTreeTest {
   public static void main(String args[]) throws IOException {
      Runtime.getRuntime().exec("cmd");
     
      System.out.println("Showing children processes:");
      ProcessHandle processHandle = ProcessHandle.current();
      processHandle.children().forEach(childProcess ->
              System.out.println("PID: " + childProcess.pid() + " Command: " + childProcess.info().command().get()));
     
      System.out.println("Showing descendant processes:");
      processHandle.descendants().forEach(descendantProcess ->
              System.out.println("PID: " + descendantProcess.pid() + " Command: " +   descendantProcess.info().command().get()));
   }
}
为了杀死进程及其子进程,Java9使用了API 迭代过程的所有
子项
,并对每个子项调用
destroy

例如:在您的例子中,您从ApacheCommons获取Process对象,然后尝试以下代码

Process child = ...;
kill (child.toHandle());

public void kill (ProcessHandle handle)
{
    handle.descendants().forEach((child) -> kill(child));
    handle.destroy();
}
参考资料:

注意-我没有尝试过这个特性,只是阅读了有关Java9和 发现有助于分享这里


不幸的是,这些脚本是windows.bat脚本。所以我不确定windows脚本中是否提供了捕获杀戮命令的机制。我对这个问题做了一些背景研究。无法在Process.destroy()方法中终止子进程。在windows上解决此问题的任何解决方案都应该通过调用本机库来实现。