强制杀死子进程的 Java 工具/方法 [英] Java tool/method to force-kill a child process

查看:24
本文介绍了强制杀死子进程的 Java 工具/方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking for a Java tool/package/library that will allow me to force-kill a child process.

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

This tool/package/library must work on Windows platform (mandatory). Support for Linux/Unix is desired.

我的 Java 代码创建了一个子进程,它根本不会响应杀死子进程的标准 Java 方法:process.destroy(),以及,由于我没有孩子的源代码,我无法将其编程为更好地处理终止请求.

My Java code creates a child process that will simply not react to the standard Java way for killing a child process: process.destroy(), and, since I do not have the child's source code, I cannot program it to better handle termination requests.

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

I have tried closing the child process' error input and output stream before calling destroy(), and for no effect.

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

I have even tried passing ctrlBreak signal (char=3) directly into child.getOutputStream(), and again have received the same results.

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

The workaround I have finally managed to find was to:

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

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

Use the child's PID to issue a force kill system command
in Windows: getRuntime().exec("taskkill /pid " + childPid + " /f")

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

But - this is complex code I have no desire to debug and maintain, plus the problem itself, I have no doubt, was previously encountered by many other java developers, which leads me to the hope that such a Java tool/package/library already exists.

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

I just don't know its name...

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

PS: My child process was created by Runtime.getRuntime().exec(cmd), but I get the same behaviour using a ProcessBuilder.

推荐答案

使用 Java JNA 有一种更精简的方法可以做到这一点.

There is a leaner way to do this using Java JNA.

这绝对适用于 Windows 和 Linux,我假设您也可以对其他平台执行相同的操作.

This works definitely for Windows and Linux, i assume that you can do the same for other platforms too.

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

The biggest problem of Java process handling is the lack of a method to get the process id of the process started with untime.getRuntime().exec().

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

Assuming you got the pid of a process, you always can start a kill -9 command in linux, or use similar ways to kill a process in windows.

这是一种为 linux 本地获取进程 ID 的方法(从 selenium 框架借来,:)),并且在 JNA 的帮助下,这也可以为 windows 完成(使用本地 Windows API 调用).

Here is a way to get the process id natively for linux (borrowed from the selenium framework, :) ), and with the help of JNA this also can be done for windows (using native Windows API calls).

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

For this to work (for Windows) you first have to get the JNA Library at JAVA NATIVE ACCESS (JNA): Downloads or get it from maven

看下面的代码,它会得到一个(在这个例子中是windows)程序的pid(大部分代码实际上是碎片,让java程序运行起来):

Look at the following code, which will get the pid of a (in this example windows) program (most of the code is actually debris to get a working java program going):

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

希望这会有所帮助,;)...

Hope this helps, ;)...

这篇关于强制杀死子进程的 Java 工具/方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆