Можно ли убить виртуальную машину Java с другой виртуальной машины? - PullRequest
4 голосов
/ 15 сентября 2008

У меня есть приложение Java, которое запускает другое приложение Java. Модуль запуска имеет сторожевой таймер и периодически получает уведомления от второй виртуальной машины. Однако если уведомления не получены, вторая виртуальная машина должна быть уничтожена, и программа запуска выполнит некоторые дополнительные действия по очистке.

Вопрос в том, есть ли способ сделать это, используя только Java? до сих пор я использовал некоторые нативные методы для выполнения этой операции, и это как-то некрасиво.

Спасибо!

Ответы [ 9 ]

6 голосов
/ 15 сентября 2008

Возможно, я что-то упускаю, но вы не можете вызвать метод destroy() для объекта Process, возвращаемого Runtime.exec()?

3 голосов
/ 15 сентября 2008

Вы можете использовать java.lang.Process , чтобы делать то, что вы хотите. Создав вложенный процесс и получив ссылку на экземпляр Process, вы можете получить ссылки на его стандартные потоки out и err. Вы можете периодически отслеживать их и вызывать .destroy (), если хотите закрыть процесс. Все это может выглядеть примерно так:

Process nestedProcess = new ProcessBuilder("java mysubprocess").start();
InputStream nestedStdOut = nestedProcess.getInputStream(); //kinda backwards, I know
InputStream nestedStdErr = nestedProcess.getErrorStream();
while (true) {
    /*
       TODO: read from the std out or std err (or get notifications some other way)
       Then put the real "kill-me" logic here instead of if (false)
    */
    if (false) {
        nestedProcess.destroy();
        //perform post-destruction cleanup here
        return;
    }

    Thread.currentThread().sleep(1000L); //wait for a bit
}

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

Sean

2 голосов
/ 17 сентября 2008

Обычный способ сделать это - вызвать Process.destroy () ... однако это неполное решение, так как при использовании Sun JVM в * nix уничтожают карты на SIGTERM, который не гарантирует прекращение процесса (для что тебе тоже нужен SIGKILL). Конечным результатом является то, что вы не можете осуществлять реальное управление процессами с помощью Java.

Есть несколько открытых ошибок по этой проблеме, см .: текст ссылки

2 голосов
/ 15 сентября 2008

Вы также можете опубликовать службу (через мешковину, гессиан и т. Д.) На второй JVM, которая вызывает System.exit (), и использовать ее из сторожевой JVM. Если вы хотите отключить вторую JVM только тогда, когда она прекращает отправку этих периодических уведомлений, возможно, она не в состоянии отвечать на вызов службы.

Вероятно, лучше всего вызывать команды оболочки с помощью java.lang.Runtime.exec ().

1 голос
/ 17 сентября 2008

ОК, суть заключается в следующем:

Я использовал Process API для закрытия второй виртуальной машины, но это не сработало.

Причина в том, что мое второе приложение - приложение Eclipse RCP, и я запустил его с помощью включенного модуля запуска eclipse.exe.

Однако это означает, что метод destroy API процесса нацелен на процесс eclipse.exe. Уничтожение этого процесса оставляет процесс Java невредимым. Итак, один из моих коллег здесь написал небольшое приложение, которое убьет правильное приложение.

Таким образом, одно из решений для использования Process API (и удаления лишних промежуточных шагов) заключается в том, чтобы избавиться от средства запуска Eclipse, в котором моя первая виртуальная машина дублировала все ее функции.

Полагаю, мне нужно будет приступить к работе.

1 голос
/ 15 сентября 2008

java.lang.Process имеет метод waitFor () для ожидания завершения процесса и метод destroy () для уничтожения подпроцесса.

0 голосов
/ 15 сентября 2008

Не совсем управление процессами, но вы можете запустить сервер rmi на виртуальной машине Java, которую вы запускаете, и связать удаленный экземпляр с методом, который выполняет необходимую очистку и вызывает System.exit () , Первый vm может затем вызвать этот удаленный метод для отключения второго vm.

0 голосов
/ 15 сентября 2008

Вы можете сделать так, чтобы java-код обнаруживал платформу во время выполнения и запускал команду kill process платформы. Это действительно уточнение вашего текущего решения.

Существует также Process.destroy () , если вы используете ProcessBuilder API

0 голосов
/ 15 сентября 2008

Вы должны быть в состоянии выполнить команды java.lang.Runtime.exec и shell.

...