强制杀死子进程的 Java 工具/方法 [英] Java tool/method to force-kill a child process
问题描述
我正在寻找一个可以让我强制杀死的 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:
在创建时获取孩子的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屋!