Есть ли способ перезагрузить JVM? Например, не выходить на самом деле, а закрывать и перезагружать все классы и запускать main сверху?
@HotLicks, да, потому что мы все прирожденные эксперты во всем, верно?
@ununiform - потому что для этого требуется достаточно глубокое знание JVM и ее интерфейса с ОС.




AFAIK такого пути нет.
Обратите внимание, что если бы был способ сделать это, то правильное освобождение всех удерживаемых ресурсов для обеспечения плавного перезапуска во многом зависело бы от текущего загруженного кода (подумайте о файлах, соединениях socket / tcp / http / database, потоках и т. д. ).
Некоторые приложения, такие как Jboss AS, захватывают Ctrl + C на консоли и обеспечивают плавное завершение работы, закрывая все ресурсы, но это специфичный для приложения код, а не функция JVM.
В JVM IBM есть функция, называемая «сбрасываемой», которая позволяет вам эффективно делать то, что вы просите.
Я не думаю, что это возможно, кроме 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, а затем «перезагружаю» его. Я уверен, что за кулисами они используют другой загрузчик классов.
Не настоящая "перезагрузка", но:
Вы можете создать свой собственный загрузчик классов и загрузить с ним все свои классы (кроме начальной загрузки). Затем, когда вы захотите «перезагрузиться», убедитесь, что вы сделали следующее:
Эта процедура используется (в некоторой степени) при «горячей замене» веб-приложений на веб-серверах.
Однако обратите внимание, что статические члены класса и «глобальные» объекты JVM (те, к которым обращается корень сборщика мусора, который не находится под вашим контролем) останутся. Например, Locale.setLocale () влияет на статический член Locale. Поскольку класс Locale загружается загрузчиком системного класса, он не будет «перезапущен». Это означает, что старый объект Locale, который использовался в Locale.setLocale (), будет доступен позже, если его не очистить явно.
Еще один путь, который следует избрать, - это инструментирование занятий. Однако, поскольку я мало знаю об этом, я не решаюсь давать советы.
Что ж, в настоящее время у меня есть это, он отлично работает и полностью не зависит от ОС. Единственное, что должно работать: выполнение java-процесса без пути / и т.д., но я думаю, что это тоже можно исправить.
Небольшие фрагменты кода взяты из stackoverflow, кроме RunnableWithObject и restartMinecraft () :)
Назвать его нужно так:
restartMinecraft(getCommandLineArgs());
Итак, что он в основном делает:
И да, это прямо взято из моего проекта 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 () или начать сначала().
Возможно, вы захотите рассказать немного больше о предыстории. Что вы пытаетесь достичь?