簡體   English   中英

有什么方法可以“重啟”JVM?

[英]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”的功能,可以讓您有效地完成您的要求。

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

除了IBM JVM之外,我認為不可能。

不是真正的“重啟”但是:

您可以構建自己的類加載器並使用它加載所有類(引導程序除外)。 然后,當您想要“重新啟動”時,請確保執行以下操作:

  1. 結束您打開並正在使用您的類的所有線程。
  2. 處理您創建的任何窗口/對話框/小程序(UI應用程序)。
  3. 關閉/處置任何其他GC根/ OS資源飢餓的對等資源(數據庫連接等)。
  4. 扔掉你的自定義類加載器,創建它的另一個實例並重新加載所有類。 您可以通過預處理文件中的類來優化此步驟,這樣您就不必再次訪問代碼庫。
  5. 打電話給您的主要入場點。

在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());

它的基本功能是:

  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;
}

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM