特定のURLから新しいバージョン(.jarファイル)をダウンロードし、実行時に自分自身を更新できるJavaアプリケーション(サーバーアプリケーション)を実装したいと思います。
これを行う最善の方法は何ですか?それは可能ですか?
アプリケーションが新しい.jarファイルをダウンロードして起動できると思います。しかし、どのようにハンドオーバーを行うべきですか?新しいアプリケーションがいつ開始されたかを確認してから終了します。または、これを行うためのより良い方法はありますか?
ソリューションの基本構造は次のとおりです。
アプリの最新バージョン(必要な場合)を繰り返し読み込み、起動するメインループがあります。
アプリケーションは処理を行いますが、ダウンロードURLを定期的にチェックします。新しいバージョンを検出すると、終了してランチャーに戻ります。
これを実装する方法はいくつかあります。例えば:
ランチャーは、ラッパースクリプトまたは新しいJVMを起動して、置き換えられるJARファイルからアプリケーションを実行するバイナリアプリケーションにすることができます。
ランチャーはJava新しいJAR用のクラスローダーを作成し、エントリポイントクラスをロードし、そのメソッドを呼び出すアプリケーションです。この方法で行う場合、クラスローダーストレージを監視する必要がありますリークしますが、それは難しくありません(再起動後、JARからロードされたクラスを持つオブジェクトが到達できないことを確認する必要があります)。
外部ラッパーアプローチの利点は次のとおりです。
2番目のアプローチには2つのJARが必要ですが、次の利点があります。
「最良の」方法は、特定の要件によって異なります。
次の点にも注意する必要があります。
自動更新にはセキュリティ上のリスクがあります。一般に、更新を提供するサーバーが危険にさらされている場合、または更新を提供するメカニズムが攻撃を受けやすい場合、自動更新によりクライアントが危険にさらされる可能性があります。
クライアントに損害を与える更新をクライアントにプッシュすると、法的リスク、およびビジネスの評判に対するリスクが生じる可能性があります。
車輪の再発明を避ける方法を見つけることができれば、それは良いことです。提案については、他の回答を参照してください。
現在、Java Linux Daemonを開発しています。また、自動更新メカニズムを実装する必要がありました。アプリケーションを1つのjarファイルに制限したかったので、簡単な解決策を思い付きました。
アップデーターアプリケーションをアップデート自体にパックします。
アプリケーション:アプリケーションが新しいバージョンを検出すると、次のことを行います。
ApplicationUpdater:アップデーターが実行されると、以下を実行します。
それが誰かを助けることを願っています。
Javaランタイムでプラグインをロードし、すぐに使用を開始できるアプリケーションを作成しました。jEditの同様のメカニズムに触発されました。jEditはオープンソースであるため、できます。
このソリューションでは、カスタムClassLoaderを使用して、jarからファイルをロードします。ロードされたら、main
メソッドとして機能する新しいjarからメソッドを呼び出すことができます。トリッキーな部分は、古いコードへのすべての参照を確実に削除して、ガベージコレクションできるようにすることです。私はその部分の専門家ではありません。機能させましたが、簡単ではありませんでした。
これは既知の問題であり、車輪の再発明を避けることをお勧めします-自分でハックを書くのではなく、他の人がすでにやったことを使ってください。
考慮する必要がある2つの状況:
アプリは自己更新可能で、更新中でも実行し続ける必要があります(サーバーアプリ、組み込みアプリ)。 OSGiを使用します: Bundles または Equinox p2 。
アプリはデスクトップアプリであり、インストーラーがあります。更新オプションを備えた多くのインストーラーがあります。 インストーラーリスト を確認します。
最近、 pdate4j を作成しました。これは、Java 9のモジュールシステムと完全に互換性があります。
再起動せずに新しいバージョンをシームレスに起動します。
これは必ずしもbestの方法ではありませんが、うまくいくかもしれません。
bootstrapアプリケーション(WoWをプレイしている場合はWorld of Warcraftランチャー))を記述できます。そのbootstrapは更新の確認を担当します。
これにより、アプリケーションを強制終了することを心配する必要がなくなります。
アプリケーションがWebベースであり、最新のクライアントを持っていることが重要な場合は、アプリケーションの実行中にバージョンチェックを行うこともできます。サーバーとの通常の通信(一部またはすべての呼び出し)、またはその両方を実行しながら、間隔を空けて行うことができます。
私が最近取り組んだ製品については、起動時(ブートストラップアプリなしで、メインウィンドウが表示される前)、およびサーバーへの呼び出し中にバージョンチェックを行いました。クライアントが古くなった場合、ユーザーが手動で終了することに依存していましたが、サーバーに対するアクションは禁止されていました。
Javaがメインウィンドウを表示する前にUIコードを呼び出すことができるかどうかはわかりません。C#/ WPFを使用していました。
Equinox プラグインを使用してアプリケーションを構築する場合、 P2 Provisioning System を使用して、この問題に対する既製のソリューションを取得できます。これには、更新後にサーバーを再起動する必要があります。