3

システム全体をダウンさせることなく定期的に「更新」する予定の OSGi ベースのシステムを開発しています。バンドルの変更を容易にするために「更新」を使用するつもりであり、理論を証明するために小さなアプリ (2 バンドル) を作成しました。

私の最終目標: OSGi を使用してバンドルを動的に更新できるプラットフォームを実装しようとしています。

これまでのところ: 2 つのバンドルを作成しました。数学バンドル (加算と乗算が可能な 2 つのメソッドがあります) と、毎秒実行されるスレッドを持ち、2 つの乱数を生成し、前述の数学バンドルを使用してそれらを加算および乗算 (および結果を表示) する表示バンドルです私は宣言型サービスを使用しているため、インターフェイス IMath によって定義されたサービスをエクスポートする数学バンドルにコンポーネント定義があります。同様に、IMath インターフェイスで定義されたサービスにサブスクライブする (1:1 静的)ディスプレイバンドルにコンポーネント定義があります。各コンポーネントの起動/シャットダウンの各段階で典型的なデバッグ メッセージが表示されます。

プロジェクトが開始されると、通常は次のように表示されます。

Starting up Math...
Starting up Display...
Running the Display thread...

その後、毎秒、表示スレッドが計算を行っていることがわかります。さらに、次のことができます (数学がバンドル 1 で、ディスプレイがバンドル 2 であると仮定します)。

> stop 1
Stopping the Display thread...
Display bundle has been shut down.
Math bundle has been shut down
> start 1
Starting up Math...
Starting up Display...
Running the Display thread...

問題:ここまでは順調ですよね? 「更新」コマンドを使用しようとするまで、すべてが順調に進んでいます。この場合、乗算計算でエラーが発生したため、数学バンドルを更新したいと考えています。

> update 1
Stopping the Display thread...
Display bundle has been shut down.
Math bundle has been shut down
Starting up Math...

何?ds がスタートアップ メソッドを呼び出してディスプレイバンドルを再起動しなかったのはなぜですか? ディスプレイバンドルも更新してみましたが、問題なく動作しているようです。バンドルを更新すると再起動するような気がしますが、更新されたバンドルのサービスにサブスクライブするバンドルは、宙ぶらりんのままです。

さらに悪いことに、ディスプレイバンドルを停止して開始しても、まだ起動しません。

私は何かを間違った方法で見ていると確信しているので、誰かが私の問題に光を当てることができればいいと思います. ソース コードが必要な場合はお知らせください。基本的な Java ファイルをいくつか添付して、問題のデモを行います。

私の問題について十分に具体的でない場合は、お知らせください。推定します。

読んでくれてありがとう!アーロン

4

1 に答える 1

4

更新後に更新を行っておらず、数学バンドルによって IMath がエクスポートされていると思いますか?

バンドルを更新しても、OSGi は古いクラス ローダーを削除しません。そのローダーは、ガベージ コレクションによってのみ削除できます。つまり、クラス参照が存在しなくなります。したがって、バンドル 1 が更新されると、新しいクラス ローダーであるバンドル 1' が作成されます。ただし、バンドル 2 はまだバンドル 1 クラス ローダーにバインドされています。クラスパスの例外を防ぐために、OSGi は互換性のないサービスをバンドル 2 に表示しません。バンドル 1' は IMath' サービスを登録するため、バンドル 2 はバンドル 1 の IMath を検索するため、このサービスを認識できなくなります。そのクラス ローダーは IMath のバンドル 1 にバインドされたままです。したがって、これは作業状況です。

     +----+                +----+
     | b1 |-------<|-------| b2 |                  <| service
     +----+       v        +----+                  E  exports package
        \___E___[IMath]___I__/                     I  imports package

次に、更新を行います。

        /----E--[IMath]---I--\
     +----+        v       +----+
     | b1 |       <|       | b2 |
     +----+       |        +----+
                  |           |
                  +-----------+

     +----+         
     | b1'|-------<|
     +----+       v 
        \___E___[IMath']

更新操作は、すべてのバンドルを調べて、どのバンドルが「古い」バンドル (この場合は b2) に接続されているかを見つけます。次に、バンドル 2 を停止し、b2 のクラスローダーへのすべての参照が削除されていることを確認してから、新しいクラスローダーで b2 を再度開始して、b1' に解決できるようにします。b2 は更新操作の前に開始されたため、再度開始します。

                           +----+
                      +----| b2 |
                      |    +----+
                      |       |
     +----+           |       |
     | b1'|-------<|--+       |
     +----+       v           |
        \_______[IMath']______/

これは通常、人々に疑問を残します。更新と更新を組み合わせてみませんか? どうすればこれを処理できますか。

OSGi 1.0 では、この曖昧な段階について議論していました (私たちはそれが存在することに気付いていなかったと思います)。そのため、OSGi 2 では、一部のベンダーは「積極的」(更新と更新の組み合わせ) であり、一部のベンダーは怠け者 (そしてまったく何もしなかった) であることがわかりました。もっと深く考えてみると、更新は大変な作業なので、熱心にすると大規模な更新セットが非常に非効率になることに気付きました。そのため、更新は次のように行われると仮定しました。

  1. バンドルの更新を停止する
  2. 更新する更新バンドル
  3. リフレッシュ
  4. 更新されたすべてのバンドルを開始する

このようにして、中断を最小限に抑え (更新されたバンドルは 1 回だけ停止/開始します)、バンドルは 1 回だけ更新されます。bnd ランチャーを見ると、このパターンが詳細に表示されます (bnd は、IDE で変更されたバンドルを自動的に更新します)。

さて、この更新方法は非常に簡単です。ただし、一部の人々は、エッジで生活し、「最適化」を使用することを好みます。まず、IMath をエクスポートするバンドル 3 がある場合、この問題は発生しません。

     +----+
     | b1 |-I-\
     +----+   |
        |     |      +----+
        ^  [IMath]-E-| b3 |           
        |     |      +----+
     +----+   |
     | b2 |-I-/
     +----+

このコンステレーションでは、b1 の更新は問題なく、b1' が解決されると IMath が見つかり、これにより IMath サービスが登録されます。これはたまたま b2 の IMath のクラス ローダー (つまり b3) と一致します。これはそれほど混乱を招くものではありませんが、「論理的な」理由がないため、余分なバンドルを追加します。個人的には、プロバイダー (b1 など) はコントラクト (IMath) をエクスポートする必要があると思います。コントラクトは、通常下位互換性を享受するコンシューマーとは異なり、このコントラクトに非常に緊密に結合されているためです。

于 2013-07-29T08:00:59.880 に答える