我有一个跨平台(Linux和Windows)程序,目前在Java 7上运行。该程序将使用ProcessBuilder启动一个或多个工作程序作为进程(使用here中的指令):
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = MyClass.class.getCanonicalName();
ProcessBuilder pb = new ProcessBuilder(javaBin, "-cp", classpath, className);
pb.directory(null);
pb.inheritIO();
Process p = pb.start();
此方法的原因旨在解决旧系统的问题,该系统以线程运行工作程序。但是,由于我们正在运行的代码的性质,工作人员可能会进入一个他们不会退出的循环。由于Java不支持终止线程的想法,我们在假设Java实际上可以杀死进程的情况下转移到一个完全独立的进程。
然而,在Java 7中似乎不是这样 - Process.destroy()发送SIGTERM,而不是SIGKILL,并且我们停滞不前的工作人员没有像我们期望的那样被杀死。 Java 8实现了Process.destroyForcibly(),它可以解决问题,但升级核心Java版本可能会引入一些错误,如果可能的话,升级是我们想要避免的。
大多数其他解决方案涉及反映到UNIXProcess类,获取pid,并将kill命令传递给shell。但是,这对我们来说不起作用,因为我们在Windows上运行,其中Process没有掌握pid,并且进一步迫使我们包含特定于操作系统的代码路径,这是非常不受欢迎的。
是否有一些可靠的方法让Java终止某些东西?
答案 0 :(得分:1)
您可以尝试使用此API SIGAR。
示例代码:
final Sigar sigar = new Sigar();
final long[] processes = sigar.getProcList();
for (final long processId : processes) {
System.out.println(processId + " = " + ProcUtil.getDescription(sigar, processId));
final String processDescription = ProcUtil.getDescription(sigar, processId);
if(processDescription.contains("notepad.exe")){
System.out.println("Found notepad.exe with id [" + processId + "] - KILLING IT!");
sigar.kill(processId, -9);
}
}
代码来源:Link
答案 1 :(得分:0)
我的情况下的解决方案,因为我正在编写父进程和子进程,就是添加一个停止JVM的ShutdownHook(一个简单的System.exit(1)是不够的):
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Runtime.getRuntime().halt(5);
}
});
在此之后,当收到SIGTERM时,进程将终止,就像它已由父进程发送SIGKILL一样。