5

Windows サービスとして実行される Java で記述されたサーバーがあります (Install4J のおかげです)。このサービスが実行元の JAR ファイルの最新バージョンをダウンロードして、新しいコードの実行を開始できるようにしたいと考えています。問題は、Windows サービスを完全に終了させたくないということです。

理想的には、現在のバージョンを停止して新しいバージョンを実行する unix スタイルの exec() 呼び出しによってこれを実現します。どうすればこれを達成できますか?

4

5 に答える 5

1

これは複雑ですが、移植可能な方法です。

コードを 2 つの jar に分割します。プロセスの起動を管理するためだけに、非常に小さな jar が 1 つあります。クラスパスに他の jar を保持する ClassLoader を作成します。

新しいバージョンをロードする場合は、古い jar からコードを実行しているすべてのスレッドを終了します。古い jar からのクラスのインスタンスへのすべての参照を無効にします。古い jar をロードした ClassLoader へのすべての参照を無効にします。この時点で、何も見逃していなければ、古いクラスと ClassLoader はガベージ コレクションの対象になります。

ここで、新しい jar を指す新しい ClassLoader インスタンスで最初からやり直し、アプリケーション コードを再起動します。

于 2008-10-13T17:49:08.497 に答える
1

Java Service Wrapperは、これ以上のことを行います。

于 2008-10-13T23:51:52.897 に答える
1

私の知る限り、Java でこれを行う方法はありません。

Runtime.execJavaまたはProcessBuilderの start() コマンド (新しいプロセスを開始する) を使用して、現在のプロセスを終了させることで回避できると思います... ドキュメントの状態

Process オブジェクトへの参照がなくなった場合、サブプロセスは強制終了されませんが、サブプロセスは非同期で実行を続けます。

親が終了してガベージコレクトされた場合も同じことが当てはまると思います。

問題は、Runtime.exec のプロセスに有効な in、out、および err ストリームがなくなることです。

于 2008-10-13T16:29:06.833 に答える
0

Tomcat、Jetty、JBoss などの組み込みのリロード機能を使用できます。それらはサービスとして実行でき、Web コンテナーまたは Java EE コンテナーとして使用する必要はありません。

その他のオプションは、OSGi と独自のクラス ロード機能です。

ただし、本番環境でのリロードに注意してください。それが常に最善の解決策であるとは限りません。

于 2008-10-13T17:55:17.780 に答える
-2

一般的方法:

import java.io.BufferedInputStream;
import java.util.Arrays;

public class ProcessSpawner {    
public static void main(String[] args) {
    //You can change env variables and working directory, and
    //have better control over arguments.
    //See [ProcessBuilder javadocs][1]
    ProcessBuilder builder = new ProcessBuilder("ls", "-l");

    try {
        Process p = builder.start();
        //here we just echo stdout from the process to java's stdout.
        //of course, this might not be what you're after.
        BufferedInputStream stream = 
            new BufferedInputStream(p.getInputStream());
        byte[] b = new byte[80];
        while(stream.available() > 0) {                 
            stream.read(b);
            String s = new String(b);
            System.out.print(s);
            Arrays.fill(b, (byte)0);
        }
        //exit with the exit code of the spawned process.
        System.exit(p.waitFor());

    } catch(Exception e) {
        System.err.println("Exception: "+e.getMessage());
        System.exit(1);
    }
  }
}
于 2008-10-13T16:59:09.033 に答える