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

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

问题描述

我正在寻找一个Java工具/包/库,它允许我强制杀死
a子进程。



这个工具/包/库必须在Windows平台上工作(必须)。
需要支持Linux / Unix。



我的问题



我的Java代码创建了一个孩子这个过程根本不会对用于杀死子进程的
标准Java方法做出反应:process.destroy()和
,因为我没有孩子的源代码,我无法将其编程为
更好地处理终止请求。



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



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



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


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


  2. 使用孩子的PID发出强制终止系统命令

    在Windows中: getRuntime()。exec(taskkill / pid+ childPid +/ f)


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



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



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

解决方案

那里使用Java JNI是一种更精简的方法。



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



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



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



这是一种为linux本身获取进程id的方法(借用selenium framework,:)),在JNI的帮助下,这也可以用于windows(使用本机Windows API调用)。



为了使其正常工作(对于Windows),首先必须在 JAVA NATIVE ACCESS(JNA):下载



查看下面的代码,它将获得a的pid(in这个例子是windows程序(大部分代码实际上都是碎片来获得正常工作的java程序):

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

公共类Main {

静态接口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(PID:+ getPid(p));

int x = p.waitFor();
System.out.println(退出时使用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));
返回pid;
} catch(Exception ex){
Logger.getLogger(Main.class.getName())。log(Level.SEVERE,null,ex);
}
}否则if(Platform.isLinux()){
try {
f = p.getClass()。getDeclaredField(pid);
f.setAccessible(true);
int pid =(整数)f.get(p);
返回pid;
} catch(Exception ex){
Logger.getLogger(Main.class.getName())。log(Level.SEVERE,null,ex);
}
}
else {}
返回0;
}
}

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


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

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

My Problem

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.

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

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. Obtain the child's PID upon its creation This can be done in Windows by diffing the process lists before and after the child's creation (getRuntime().exec("tasklist /v"))

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

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: My child process was created by Runtime.getRuntime().exec(cmd), but I get the same behaviour using a ProcessBuilder.

解决方案

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

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

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().

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.

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

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

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天全站免登陆