[英]Any way to “reboot” the JVM?
有沒有辦法重啟JVM? 就像在實際上不退出,但關閉並重新加載所有類,並從頂部運行main?
你最好的選擇可能是在循環中運行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)表示您要停止並保持停止狀態。
IBM的JVM有一個名為“resettable”的功能,可以讓您有效地完成您的要求。
除了IBM JVM之外,我認為不可能。
不是真正的“重啟”但是:
您可以構建自己的類加載器並使用它加載所有類(引導程序除外)。 然后,當您想要“重新啟動”時,請確保執行以下操作:
在Web服務器中“熱交換”Web應用程序時(在某種程度上)使用此過程。
但請注意,靜態類成員和JVM“全局”對象(由不受您控制的GC根訪問的對象)將保留。 例如,Locale.setLocale()在Locale上生成靜態成員。 由於Locale類由系統類加載器加載,因此不會“重新啟動”。 這意味着如果未明確清除,Locale.setLocale()中使用的舊Locale對象將在以后可用。
還有另一種方法是上課。 但是,由於我對它知之甚少,我對提供建議猶豫不決。
如果您在應用程序服務器中工作,它們通常會帶有內置的熱部署機制,當您重新部署它時,它會重新加載應用程序中的所有類(Web應用程序,企業應用程序)。
否則,您將不得不考慮商業解決方案。 Java Rebel( http://www.zeroturnaround.com/javarebel/ )就是這樣一個選擇。
好吧,我目前有這個,它運行完美,完全獨立於操作系統。 唯一必須工作的是:執行沒有任何路徑/ etc的java進程,但我認為這也可以修復。
除了RunnableWithObject和restartMinecraft():)之外,所有小代碼都來自stackoverflow。
你需要像這樣調用它:
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;
}
Aaaaand最后是RunnableWithObject類:
package generic.minecraft.infinityclient;
public abstract class RunnableWithObject<T> implements Runnable {
public T data;
}
祝好運 :)
AFAIK沒有這樣的方法。
請注意,如果有辦法做到這一點,它將高度依賴於當前加載的代碼來正確釋放所有保留的資源,以便提供正常的重新啟動(考慮文件,socket / tcp / http /數據庫連接,線程等)。
某些應用程序(如Jboss AS)在控制台上捕獲Ctrl + C並提供正常關閉,關閉所有資源,但這是特定於應用程序的代碼而不是JVM功能。
我使用JMX做類似的事情,我將使用JMX“卸載”一個模塊,然后“重新加載”它。 在幕后我肯定他們正在使用不同的類加載器。
在JavaX中很容易:您可以使用標准函數nohupJavax()或restart() 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.