Есть ли способ «перезагрузить» JVM?

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

Возможно, вы захотите рассказать немного больше о предыстории. Что вы пытаетесь достичь?

James Van Huis 03.11.2008 20:45

@HotLicks, да, потому что мы все прирожденные эксперты во всем, верно?

ununiform 16.12.2014 19:56

@ununiform - потому что для этого требуется достаточно глубокое знание JVM и ее интерфейса с ОС.

Hot Licks 16.12.2014 20:01
dzone.com/articles/programmatically-restart-java
Koekiebox 21.08.2017 13:41
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
34
4
80 409
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

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

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

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

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

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

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

Ответ принят как подходящий

Лучше всего, вероятно, запустить интерпретатор 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), чтобы указать, что вы хотите остановиться и оставаться остановленным.

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

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

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

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

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

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

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

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

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

Небольшие фрагменты кода взяты из stackoverflow, кроме 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;
}

Удачи :)

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

Другие вопросы по теме