Gil*_*mov 14 java kill process
我正在寻找一个允许我强制杀死子进程的Java工具/包/库.
此工具/包/库必须在Windows平台上运行(必需).需要支持Linux/Unix.
我的Java代码创建了一个子进程,它根本不会对用于终止子进程的标准Java方法做出反应:process.destroy(),并且,由于我没有子进程的源代码,我无法对其进行编程以更好地处理终止请求.
我已经尝试在调用destroy()之前关闭子进程的错误输入和输出流,并且没有效果.
我甚至尝试将ctrlBreak信号(char = 3)直接传递给child.getOutputStream(),并再次收到相同的结果.
我终于找到的解决方法是:
在创建时获取子PID这可以通过在子项创建之前和之后区分进程列表在Windows中完成(getRuntime().exec("tasklist /v")
)
使用子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)
希望这可以帮助, ;)...