Любой способ перезагрузить JVM? - PullRequest
31 голосов
/ 03 ноября 2008

Есть ли способ перезагрузить JVM? Как на самом деле не выходить, но закрыть и перезагрузить все классы и запустить main сверху?

Ответы [ 8 ]

17 голосов
/ 03 ноября 2008

Лучше всего, вероятно, запустить Java-интерпретатор в цикле и просто выйти. Например:

#!/bin/sh
while true
do
    java MainClass
done

Если вы хотите полностью перезагрузиться или выключиться, вы можете проверить состояние выхода:

#!/bin/sh
STATUS=0
while [ $STATUS -eq 0 ]
do
    java MainClass
    STATUS=$?
done

В java-программе вы можете использовать System.exit (0), чтобы указать, что вы хотите «перезагрузиться», и System.exit (1), чтобы указать, что вы хотите остановиться и остаться остановленным.

7 голосов
/ 03 ноября 2008

В IBM JVM есть функция, называемая «перезагружаемая», которая позволяет вам эффективно выполнять то, что вы просите.

http://publib.boulder.ibm.com/infocenter/cicsts/v3r1/index.jsp?topic=/com.ibm.cics.ts31.doc/dfhpj/topics/dfhpje9.htm

Кроме IBM JVM, я не думаю, что это возможно.

2 голосов
/ 04 ноября 2008

Не настоящая "перезагрузка", но:

Вы можете создать свой собственный загрузчик классов и загрузить все свои классы (кроме начальной загрузки) с ним. Затем, когда вы хотите «перезагрузиться», убедитесь, что вы делаете следующее:

  1. Завершите все потоки, которые вы открыли и используете ваши классы.
  2. Удалите все созданные вами окна / диалоги / апплеты (приложения с пользовательским интерфейсом).
  3. Закрыть / утилизировать любые другие ресурсы для голодных одноранговых ресурсов GC root / OS (соединения с базой данных и т. Д.).
  4. Выбросьте свой настроенный загрузчик классов, создайте еще один экземпляр и перезагрузите все классы. Вероятно, вы можете оптимизировать этот шаг, предварительно обработав классы из файлов, чтобы вам больше не пришлось обращаться к базе кода.
  5. Позвоните в вашу главную точку входа.

Эта процедура используется (в некоторой степени) при «горячей» замене веб-приложений на веб-серверах.

Обратите внимание, что статические члены класса и "глобальные" объекты JVM (те, к которым имеет доступ корень GC, который не находится под вашим контролем) останутся. Например, Locale.setLocale () воздействует на статический член в Locale. Поскольку класс Locale загружается загрузчиком системного класса, он не будет перезапущен. Это означает, что старый объект Locale, который использовался в Locale.setLocale (), будет доступен позже, если не будет явно очищен.

Еще один путь - инструктаж классов. Однако, поскольку я мало что знаю об этом, я не решаюсь дать совет.

Объяснение о горячем развертывании с некоторыми примерами

1 голос
/ 03 ноября 2008

Если вы работаете на сервере приложений, они, как правило, поставляются со встроенными механизмами горячего развертывания, которые перезагрузят все классы в вашем приложении (веб-приложение, корпоративное приложение) при повторном его развертывании.

В противном случае вам придется искать коммерческие решения. Java Rebel (http://www.zeroturnaround.com/javarebel/) является одним из таких вариантов.

0 голосов
/ 02 августа 2016

Это просто в JavaX: вы можете использовать стандартные функции nohupJavax () или restart () .

0 голосов
/ 01 июня 2014

Ну, у меня в настоящее время есть это, оно прекрасно работает и полностью независим от ОС. Единственное, что должно работать: выполнение процесса Java без пути / etc, но я думаю, что это также можно исправить.

Все маленькие кусочки кода взяты из стека overflow, кроме RunnableWithObject и restartMinecraft ():)

Вам нужно назвать это так:

restartMinecraft(getCommandLineArgs());

Итак, что он в основном делает, это:

  1. Создает новый процесс и сохраняет его в переменной p
  2. Создает два экземпляра RunnableWithObject и заполняет объект процесса их значением данных, затем запускает два потока, они просто печатают inputStream и errorStream, когда у него есть доступные данные, до тех пор, пока процесс не завершится
  3. Ожидание завершения процесса
  4. печатает отладочное сообщение о выходе из процесса
  5. Завершается значением выхода процесса (не обязательно)

И да, это прямо из моего проекта Minecraft:)

код:

Метод Tools.isProcessExited ():

public static boolean isProcessExited(Process p) {
    try {
        p.exitValue();
    } catch (IllegalThreadStateException e) {
        return false;
    }
    return true;
}

Tools.restartMinecraft () метод:

    public static void restartMinecraft(String args) throws IOException, InterruptedException {
//Here you can do shutdown code etc
        Process p = Runtime.getRuntime().exec(args);
        RunnableWithObject<Process> inputStreamPrinter = new RunnableWithObject<Process>() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (!Tools.isProcessExited(data)) {
                    try {
                        while (data.getInputStream().available() > 0) {
                            System.out.print((char) data.getInputStream().read());
                        }
                    } catch (IOException e) {
                    }
                }
            }
        };
        RunnableWithObject<Process> errorStreamPrinter = new RunnableWithObject<Process>() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (!Tools.isProcessExited(data)) {
                    try {
                        while (data.getErrorStream().available() > 0) {
                            System.err.print((char) data.getErrorStream().read());
                        }
                    } catch (IOException e) {
                    }
                }
            }
        };

        inputStreamPrinter.data = p;
        errorStreamPrinter.data = p;

        new Thread(inputStreamPrinter).start();
        new Thread(errorStreamPrinter).start();
        p.waitFor();
        System.out.println("Minecraft exited. (" + p.exitValue() + ")");
        System.exit(p.exitValue());
    }

Метод Tools.getCommandLineArgs ():

public static String getCommandLineArgs() {
    String cmdline = "";
    List<String> l = ManagementFactory.getRuntimeMXBean().getInputArguments();
    cmdline += "java ";
    for (int i = 0; i < l.size(); i++) {
        cmdline += l.get(i) + " ";
    }
    cmdline += "-cp " + System.getProperty("java.class.path") + " " + System.getProperty("sun.java.command");

    return cmdline;
}

Аааа и наконец класс RunnableWithObject:

package generic.minecraft.infinityclient;

public abstract class RunnableWithObject<T> implements Runnable {
    public T data;
}

Удачи:)

0 голосов
/ 03 ноября 2008

Я делаю нечто подобное с помощью JMX, я «выгружаю» модуль с помощью JMX, а затем «перезагружаю» его. За кулисами я уверен, что они используют другой загрузчик классов.

0 голосов
/ 03 ноября 2008

AFAIK такого пути нет.

Обратите внимание, что если бы был способ сделать это, то от текущего загруженного кода сильно зависело бы правильное освобождение всех удерживаемых ресурсов для обеспечения плавного перезапуска (подумайте о файлах, соединениях с сокетом / tcp / http / database, темы и т. д.).

Некоторые приложения, например Jboss AS, захватывают Ctrl + C на консоли и обеспечивают плавное завершение работы, закрывая все ресурсы, но это код для конкретного приложения, а не функция JVM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...