web-dev-qa-db-ja.com

JVMを「再起動」する方法はありますか?

JVMを再起動する方法はありますか?実際に終了するのではなく、すべてのクラスを閉じてリロードし、メインから実行しますか?

31
Alex

あなたの最善の策は、おそらくループ内で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)を使用して停止して停止したままにすることを示すことができます。 。

17
Andru Luvisi

IBMのJVMには、「リセット可能」と呼ばれる機能があり、ユーザーが求めていることを効果的に実行できます。

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

IBM JVM以外は、可能だとは思いません。

7
DustinB

実際の「再起動」ではありませんが、次のとおりです。

独自のクラスローダーを構築し、それを使用してすべてのクラス(ブートストラップを除く)をロードできます。次に、「再起動」する場合は、次のことを確認してください。

  1. 開いてクラスを使用しているスレッドを終了します。
  2. 作成したウィンドウ/ダイアログ/アプレットを破棄します(UIアプリケーション)。
  3. 他のGCルート/ OSリソースが空いているピアリソース(データベース接続など)をすべて閉じます。
  4. カスタマイズしたクラスローダーを破棄し、別のインスタンスを作成して、すべてのクラスをリロードします。おそらくファイルからクラスを前処理することでこのステップを最適化でき、コードベースに再度アクセスする必要がなくなります。
  5. メインエントリポイントを呼び出します。

この手順は、Webサーバーでwebappを「ホットスワップ」する際に(ある程度)使用されます。

ただし、静的クラスメンバとJVM「グローバル」オブジェクト(制御されていないGCルートによってアクセスされるオブジェクト)は残ります。たとえば、Locale.setLocale()はLocaleの静的メンバーに影響します。 Localeクラスはシステムクラスローダーによってロードされるため、「再起動」されません。つまり、Locale.setLocale()で使用されていた古いLocaleオブジェクトは、明示的にクリーンアップされていなければ、後で使用可能になります。

さらにもう1つの方法は、クラスのインスツルメンテーションです。しかし、私はそれについてほとんど知らないので、私はアドバイスを提供することをheしています。

いくつかの例を使用したホットデプロイに関する説明

2
Ran Biron

アプリケーションサーバーで作業している場合は、通常、組み込みのホットデプロイメントメカニズムが付属しており、アプリケーションを再デプロイすると、アプリケーション(Webアプリ、エンタープライズアプリ)のすべてのクラスが再ロードされます。

それ以外の場合は、商用ソリューションを検討する必要があります。 Java Rebel( http://www.zeroturnaround.com/javarebel/ )はそのようなオプションの1つです。

1
Jack Leow

私の知る限り、そのような方法はありません。

それを行う方法がある場合、現在のロードされたコードに大きく依存して、保持されているすべてのリソースを適切に解放し、グレースフルリスタートを提供することに注意してください(ファイル、ソケット/ tcp/http /データベース接続、スレッドなどについて考えてください) )。

Jboss ASなどの一部のアプリケーションは、コンソールでCtrl + Cをキャプチャし、正常なシャットダウンを提供してすべてのリソースを閉じますが、これはアプリケーション固有のコードであり、JVM機能ではありません。

0
Miguel Ping

JavaXでは簡単です。標準関数 nohupJavax() または restart() を使用できます。

0
Stefan Reich

まあ、私は現在これを持っています、それは完全に動作し、完全にOSに依存しません。唯一動作する必要があるものは、パス/ etcなしでJavaプロセスを実行することですが、これも修正できると思います。

RunnableWithObjectとrestartMinecraft()以外の小さなコードはすべてstackoverflowからのものです。

次のように呼び出す必要があります。

restartMinecraft(getCommandLineArgs());

したがって、基本的には次のようになります。

  1. 新しいプロセスを生成し、p変数に格納します
  2. 2つのRunnableWithObjectインスタンスを作成し、プロセスオブジェクトをデータ値に入力し、2つのスレッドを開始します。プロセスが終了するまで利用可能なデータがある場合、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;
}

Aaaaそして最後にRunnableWithObjectクラス:

package generic.minecraft.infinityclient;

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

幸運を :)

0

JMXを使用して同様のことを行い、JMXを使用してモジュールを「アンロード」してから「リロード」します。舞台裏では、彼らは別のクラスローダーを使用していると確信しています。

0
Javamann