Как я могу заменить текущий процесс Java, как exec в стиле Unix? - PullRequest
4 голосов
/ 13 октября 2008

У меня есть сервер, написанный на Java, который работает как служба Windows (благодаря Install4J). Я хочу, чтобы этот сервис мог загружать последнюю версию файла JAR, из которого он запускается, и запускать новый код. Дело в том, что я не хочу, чтобы служба Windows полностью выходила.

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

Ответы [ 5 ]

1 голос
/ 14 октября 2008

Java Service Wrapper делает это и многое другое.

1 голос
/ 13 октября 2008

Вот сложный, но переносимый способ.

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

Когда вы хотите загрузить новую версию, вы прекращаете все потоки, выполняющие код из старого jar. Обнулить все ссылки на экземпляры классов из старого фляги. Удалите все ссылки на ClassLoader, который загрузил старый jar. На этом этапе, если вы ничего не пропустили, старые классы и ClassLoader должны иметь право на сборку мусора.

Теперь вы начинаете все заново с нового экземпляра ClassLoader, указывающего на новый jar, и перезапускаете код приложения.

1 голос
/ 13 октября 2008

Насколько я знаю, в Java нет способа сделать это.

Полагаю, вы могли бы обойти это, используя команду Java Runtime.exec или ProcessBuilder start () (которая запускает новые процессы), затем позволяя текущему конец ... состояние документов

Подпроцесс не убивается, когда больше нет ссылок на Объект процесса, а точнее подпроцесс продолжает выполняться асинхронно.

Я предполагаю, что то же самое верно, если родительский объект завершает работу и собирает мусор.

Улов - процесс Runtime.exec больше не будет иметь действительные потоки in, out и err.

0 голосов
/ 13 октября 2008

Вы можете использовать встроенные функции перезагрузки, например, Tomcat, Jetty или JBoss, их можно запускать как службу, и вам не нужно использовать их как веб-контейнер или контейнер Java EE.

Другие опции: OSGi и ваша собственная функция загрузки классов.

Но помните о перезагрузке в производственной среде. Это не всегда лучшее решение.

0 голосов
/ 13 октября 2008

Общий подход:

import java.io.BufferedInputStream;
import java.util.Arrays;

public class ProcessSpawner {    
public static void main(String[] args) {
    //You can change env variables and working directory, and
    //have better control over arguments.
    //See [ProcessBuilder javadocs][1]
    ProcessBuilder builder = new ProcessBuilder("ls", "-l");

    try {
        Process p = builder.start();
        //here we just echo stdout from the process to java's stdout.
        //of course, this might not be what you're after.
        BufferedInputStream stream = 
            new BufferedInputStream(p.getInputStream());
        byte[] b = new byte[80];
        while(stream.available() > 0) {                 
            stream.read(b);
            String s = new String(b);
            System.out.print(s);
            Arrays.fill(b, (byte)0);
        }
        //exit with the exit code of the spawned process.
        System.exit(p.waitFor());

    } catch(Exception e) {
        System.err.println("Exception: "+e.getMessage());
        System.exit(1);
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...