简体   繁体   中英

“Kill a process tree” on windows using Java

I have a Java webstart process that is part of a windows batch script. I'm using the javaws command in a batch script in this case. This match script ( start.bat) is invoked programatically using the "apache commons exec". Under some conditions the java process invoked by javaws hangs and I'd have to kill the entire process thread starting from the batch script start.bat. Is there a programatic way of doing killing an entire process tree through apache commons exec?

I've tried using the "execWatchdog.destroyProcess();" on the "start.bat" script. However it only kills the start.bat process and not the entire process tree.

Is there a way of killing the entire process tree through apache-commons-exec or a similar code?

I've seen this question Performing equivalent of "Kill Process Tree" in c++ on windows that performs an equivalent task in c++. I'm wondering if anyone has implemented calling windows native system calls through JNI.

Finally got something workable even though its a roundabout way.

Apache Commons Exec API contains the CommandLauncher class that returns a java.lang.Process object. Thanks to the link

Here the link to get the windows Process Id from a java.lang.Process. This uses the JNA libraries.

Finally with the Process Id, here the command string that kills the process tree //String killCmd = "taskkill /F /T /PID " + JNAHandler.getPid(process);

Unfortunately, as you've discovered, there isn't a pure Java way of doing this. You'll have to resort to native commands or JNI libraries, all of which are platform-dependent and more complex than a pure Java solution would be.

It may be worth upvoting the relevant bug in the Java bug database: http://bugs.sun.com/view_bug.do?bug_id=4770092

With luck we can persuade the Java developers that the poor handling of subprocesses is worth fixing for Java 8.

Java Version 9 Onwards, Java has come up with feature that can query and kill the main process and its descendants. A code snippet to query about the child processes

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()));
   }
}

To kill the process and its children, Java9 has API Iterate through all the children of the process and call destroy on each of them

For Example : As in your case you are getting Process object from apache-commons, then try out following code

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

public void kill (ProcessHandle handle)
{
    handle.descendants().forEach((child) -> kill(child));
    handle.destroy();
}

References :

https://docs.oracle.com/javase/9/docs/api/java/lang/ProcessHandle.html

https://www.tutorialspoint.com/how-to-traverse-a-process-tree-of-process-api-in-java-9

How do i terminate a process tree from Java?

Note - I have not tried this feature, Just reading about Java9 and found helpful to share here.

As far as I know, there's no such option in commons-exec. It's not even possible to obtain the PID of whatever process you just started. You could trap the kill signal within your bash script, and have the handler kill the subprocess(es) when the script process is killed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM