用于强制终止子进程的Java工具/方法

Gil*_*mov 14 java kill process

我正在寻找一个允许我强制杀死子进程的Java工具/包/库.

此工具/包/库必须在Windows平台上运行(必需).需要支持Linux/Unix.

我的问题

我的Java代码创建了一个子进程,它根本不会对用于终止子进程的标准Java方法做出反应:process.destroy(),并且,由于我没有子进程的源代码,我无法对其进行编程以更好地处理终止请求.

我已经尝试在调用destroy()之前关闭子进程的错误输入和输出流,并且没有效果.

我甚至尝试将ctrlBreak信号(char = 3)直接传递给child.getOutputStream(),并再次收到相同的结果.

我终于找到的解决方法是:

  1. 在创建时获取子PID这可以通过在子项创建之前和之后区分进程列表在Windows中完成(getRuntime().exec("tasklist /v"))

  2. 使用子PID
    在Windows中发出强制终止系统命令:getRuntime().exec("taskkill /pid " + childPid + " /f")

但是 - 这是复杂的代码我不想调试和维护,加上问题本身,我毫不怀疑,以前遇到过许多其他java开发人员,这让我希望这样的Java工具/包/库已经存在.

我只是不知道它的名字......

PS:我的子进程是由创建的Runtime.getRuntime().exec(cmd),但我使用ProcessBuilder得到了相同的行为.

小智 8

使用Java JNI有一种更精简的方法.

这适用于Windows和Linux,我假设你也可以为其他平台做同样的事情.

Java进程处理的最大问题是缺少一种方法来获取使用untime.getRuntime().exec()启动进程的进程ID.

假设你得到了一个进程的pid,你总是可以在linux中启动kill -9命令,或者使用类似的方法来杀死windows中的进程.

这是一种为linux本地获取进程id的方法(从selenium框架中借用,)),在JNI的帮助下,这也可以用于windows(使用本机Windows API调用).

要使其工作(对于Windows),首先必须在JAVA NATIVE ACCESS(JNA)上获取JNI库:下载

看看下面的代码,它将得到一个(在这个例子中是windows)程序的pid(大多数代码实际上都是碎片以获得正常工作的java程序):

import com.sun.jna.*;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

static interface Kernel32 extends Library {

    public static Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

    public int GetProcessId(Long hProcess);
}

public static void main(String[] args) {
    try {
        Process p;

        if (Platform.isWindows())
            p = Runtime.getRuntime().exec("cmd /C ping msn.de");
        else if (Platform.isLinux())
            p = Runtime.getRuntime().exec("cmd /C ping msn.de");

        System.out.println("The PID: " + getPid(p));

        int x = p.waitFor();
        System.out.println("Exit with exitcode: " + x);

    } catch (Exception ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public static int getPid(Process p) {
    Field f;

    if (Platform.isWindows()) {
        try {
            f = p.getClass().getDeclaredField("handle");
            f.setAccessible(true);
            int pid = Kernel32.INSTANCE.GetProcessId((Long) f.get(p));
            return pid;
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    } else if (Platform.isLinux()) {
        try {
            f = p.getClass().getDeclaredField("pid");
            f.setAccessible(true);
            int pid = (Integer) f.get(p);
            return pid;
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    else{}
    return 0;
}
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助, ;)...