Инструмент / метод Java для принудительного уничтожения дочернего процесса

Я ищу инструмент / пакет / библиотеку Java, который позволит мне принудительно убить дочерний процесс.

Этот инструмент / пакет / библиотека должны работать на платформе Windows (обязательно). Желательна поддержка Linux / Unix.

Моя проблема

Мой Java-код создает дочерний процесс, который просто не реагирует на стандартный Java-способ для уничтожения дочернего процесса: process.destroy (), и, поскольку у меня нет исходного кода для ребенка, я не могу запрограммировать его, чтобы лучше обрабатывать запросы на завершение ,

Я попытался закрыть входной и выходной stream дочернего процесса, прежде чем вызвать destroy (), и без эффекта.

Я даже пробовал передать сигнал ctrlBreak (char = 3) непосредственно в child.getOutputStream () и снова получил те же результаты.

Обходной путь, который я, наконец, смог найти, заключался в следующем:

  1. Получите дочерний PID при его создании. Это можно сделать в 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 является отсутствие метода для получения идентификатора процесса процесса, запущенного с помощью функции unime.getRuntime (). Exec ().

Предполагая, что вы получили pid процесса, вы всегда можете запустить команду kill -9 в linux или использовать аналогичные способы для уничтожения процесса в Windows.

Вот способ получить идентификатор процесса для linux (заимствованный из frameworks selenium, :)), и с помощью JNI это также можно сделать для Windows (используя собственные вызовы Windows API).

Для этого (для Windows) вам сначала нужно получить JNI-библиотеку в JAVA NATIVE ACCESS (JNA): Загрузки

Посмотрите на следующий код, который получит pid программы (в этом примере Windows) (большая часть кода на самом деле является обломком для запуска рабочей 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; } } 

Надеюсь это поможет, ;)…

Я решил эту проблему в прошлом, используя тот же метод, который вы предлагаете здесь: используйте taskkill для windows и kill -9 для Unix.

В Windows вы можете использовать альтернативный WMI с помощью вызова скрипта (VBS или JS) с Java или с использованием одной из библиотек совместимости (JaWin, Jintegra, Jinterop и т. Д.),

Я не думаю, что это решение настолько сложно, насколько вы боитесь. Я думаю, что это не более 50 строк кода.

Удачи.

Для окон, использующих jna 3.5.1

 try { Process p = Runtime.getRuntime.exec("notepad"); Field f = p.getClass().getDeclaredField("handle"); f.setAccessible(true); long handLong = f.getLong(p); Kernel32 kernel = Kernel32.INSTANCE; WinNT.HANDLE handle = new WinNT.HANDLE(); handle.setPointer(Pointer.createConstant(handLong)); int pid = kernel.GetProcessId(handle); System.out.print(pid); } catch (Throwable e) { } 
  • как скомпилировать и запустить java-программу в другой Java-программе?
  • Как служба Windows может запустить процесс при создании события Timer?
  • Как я могу получить PID родительского процесса моего приложения
  • Как выполнить команду и получить вывод команды в C ++ с помощью POSIX?
  • Как узнать, какие процессы обращаются к жесткому диску в системе на основе GNU / Linux?
  • Любой способ завершить все процессы на определенном диске?
  • Метод exec () Runtime не перенаправляет вывод
  • Как я могу убить процессы диспетчера задач с помощью кода VBA?
  • Какие процессы, если они существуют, существуют между PID 0 и 4 в Windows 7?
  • Linux: Есть ли что-то похожее на «верх» для ввода-вывода?
  • Windows 7 - Высокая загрузка процессора во время простоя
  • Давайте будем гением компьютера.