97

特定の URL から新しいバージョン (.jar ファイル) をダウンロードし、実行時に更新できる Java アプリケーション (サーバー アプリケーション) を実装したいと考えています。

これを行う最善の方法は何ですか?それは可能ですか?

アプリケーションは新しい .jar ファイルをダウンロードして起動できると思います。しかし、どのようにハンドオーバーを行う必要がありますか。たとえば、新しいアプリケーションがいつ開始されてから終了するかがわかります。または、これを行うより良い方法はありますか?

4

9 に答える 9

74

ソリューションの基本構造は次のとおりです。

  • アプリの最新バージョンを (必要に応じて) 繰り返しロードして起動するメイン ループがあります。

  • アプリケーションはその役割を果たしますが、定期的にダウンロード URL をチェックします。新しいバージョンを検出すると、ランチャーに戻ります。

これを実装する方法はいくつかあります。例えば:

  • ランチャは、置換される JAR ファイルからアプリケーションを実行するために新しい JVM を開始するラッパー スクリプトまたはバイナリ アプリケーションである可能性があります。

  • ランチャは、新しい JAR のクラスローダーを作成し、エントリポイント クラスをロードして、その上で何らかのメソッドを呼び出す Java アプリケーションである可能性があります。このようにすると、クラスローダのストレージ リークに注意する必要がありますが、それは難しくありません。(再起動後に、JAR からロードされたクラスを持つオブジェクトに到達できないことを確認する必要があるだけです。)

外部ラッパー アプローチの利点は次のとおりです。

  • 必要な JAR は 1 つだけです。
  • Javaアプリ全体を置き換えることができます
  • アプリなどによって作成されたセカンダリ スレッドは、特別なシャットダウン ロジックなしで消えます。
  • アプリケーションのクラッシュなどからの回復にも対処できます。

2 番目の方法では 2 つの JAR が必要ですが、次の利点があります。

  • ソリューションは純粋な Java であり、移植可能です。
  • 切り替えが早くなり、
  • 再起動後も状態をより簡単に保持できます (モジュロ リークの問題)。

「最良の」方法は、特定の要件によって異なります。

また、次の点にも注意してください。

  • 自動更新にはセキュリティ上のリスクがあります。一般に、更新を提供するサーバーが侵害された場合、または更新を提供するメカニズムが攻撃を受けやすい場合、自動更新はクライアントの侵害につながる可能性があります。

  • クライアントに損害を与える更新をクライアントにプッシュすると、法的なリスクやビジネスの評判にリスクが生じる可能性があります。


車輪の再発明を避ける方法を見つけることができれば、それは良いことです. 提案については、他の回答を参照してください。

于 2010-10-23T06:01:46.087 に答える
45

現在、JAVA Linux デーモンを開発しており、自動更新メカニズムを実装する必要もありました。アプリケーションを 1 つの jar ファイルに制限したかったので、簡単な解決策を思い付きました。

アップデータ アプリケーションをアップデート自体にパックします。

アプリケーション: アプリケーションが新しいバージョンを検出すると、次の処理が行われます。

  1. アップデートのダウンロード (Zipfile)
  2. Applicationと ApplicationUpdater を抽出します(すべて zip ファイルに含まれています)。
  3. アップデーターを実行する

ApplicationUpdater : アップデーターが実行されると、次の処理が行われます。

  1. アプリケーションを停止します (私の場合は init.d 経由のデーモン)
  2. ダウンロードしたjarファイルをコピーして、現在のアプリケーションを上書きします
  3. アプリケーションを開始する
  4. 掃除。

それが誰かを助けることを願っています。

于 2012-11-12T10:51:56.377 に答える
14

これは既知の問題であり、車輪を再発明することはお勧めしません。独自のハックを作成しないでください。他の人が既に行ったことを使用してください。

考慮する必要がある 2 つの状況:

  1. アプリは自己更新可能で、更新中も実行し続ける必要があります (サーバー アプリ、組み込みアプリ)。OSGi: BundlesまたはEquinox p2を使用します。

  2. アプリはデスクトップ アプリであり、インストーラーがあります。更新オプションを備えた多くのインストーラーがあります。インストーラーのリストを確認してください。

于 2010-10-26T07:53:49.150 に答える
11

jEdit の同様のメカニズムに着想を得て、実行時にプラグインをロードしてすぐに使用を開始できる Java アプリケーションを作成しました。jEdit はオープン ソースであるため、その動作を確認するオプションがあります。

このソリューションでは、カスタム ClassLoader を使用して、jar からファイルをロードします。それらがロードされると、そのmainメソッドとして機能する新しい jar からいくつかのメソッドを呼び出すことができます。次に、ガベージ コレクションを実行できるように、古いコードへのすべての参照を確実に削除することが難しい部分です。私はその部分の専門家ではありません。私はそれを機能させましたが、簡単ではありませんでした。

于 2010-10-23T04:34:30.970 に答える
6
  1. 第 1 の方法: Tomcat を使用し、それがデプロイ機能です。
  2. 2 番目の方法: アプリケーションを 2 つの部分 (機能部分と更新部分) に分割し、機能部分を更新部分に置き換えます。
  3. 3番目の方法:サーバーアプリケーションで新しいバージョンをダウンロードするだけで、古いバージョンがバインドされたポートを解放し、古いバージョンが新しいバージョンを実行し(プロセスを開始)、古いバージョンがアプリケーションポートのリクエストを新しいバージョンに送信して、古いバージョン、古いバージョンを削除します終了し、新しいバージョンは古いバージョンを削除します。このような: 代替テキスト
于 2010-10-23T18:21:56.860 に答える
2

Equinoxプラグインを使用してアプリケーションを構築する場合、 P2 プロビジョニング システムを使用して、この問題に対する既製のソリューションを得ることができます。これには、更新後にサーバーを再起動する必要があります。

于 2010-10-26T07:38:57.433 に答える
2

これは必ずしも最良の方法ではありませんが、あなたにとってはうまくいくかもしれません。

ブートストラップ アプリケーションを作成できます (WoW をプレイしたことがある場合は、World of Warcraft ランチャーも同様です)。そのブートストラップは、更新のチェックを担当します。

  • アップデートが利用可能な場合は、ユーザーに提供し、ダウンロード、インストールなどを処理します。
  • アプリケーションが最新の場合、ユーザーはアプリケーションを起動できます
  • 必要に応じて、アプリケーションが最新でない場合でも、ユーザーがアプリケーションを起動できるようにすることができます

これにより、アプリケーションの強制終了について心配する必要がなくなります。

アプリケーションが Web ベースで、クライアントが最新であることが重要な場合は、アプリケーションの実行中にバージョン チェックを行うこともできます。サーバーとの通常の通信 (一部またはすべての呼び出し)、またはその両方を実行しながら、間隔を置いて実行できます。

私が最近取り組んだ製品では、起動時 (ブート ストラップ アプリは使用せず、メイン ウィンドウが表示される前) とサーバーへの呼び出し中にバージョン チェックを行いました。クライアントが古くなっているときは、ユーザーが手動で終了するように頼っていましたが、サーバーに対するアクションは禁止されていました。

メイン ウィンドウを表示する前に、Java が UI コードを呼び出すことができるかどうかはわかりません。C#/WPF を使用していました。

于 2010-10-23T04:23:39.160 に答える