5

いくつかの例に基づいて、独自のクラスローダーを実装してみました。ただし、期待どおりに機能していないと思います(Jarファイルをリロードできないなど)。Jarファイルのロードを処理するためにOSGIまたはApache Felixを使用することを推奨する参考文献はほとんどありません.Jarをロードし、Jarからクラスをインスタンス化する例はありますか?

私が達成しようとしていることの詳細..基本的に継続的に実行されるJavaコマンドラインアプリケーションがあります。実行時に JAR ファイルを動的に参照し、実行時にこれらの jar 内のクラスを参照できるようにしたいと考えています。これらの jar には、1 つ以上のサポート クラスが含まれる場合があります。これらの Jar は基本的にカスタマイズされた作業単位であり、継続的に実行されているメイン アプリケーションから特定のイベント条件によって実行されます。.. これはマルチクライアントなので、jar をプラグイン可能なタイプのワークユニットにしたかったのです。

私の現在の方向性は、「クライアント」にコーディングするためのインターフェースを提供し、クラスを jar ファイルにパッケージ化することです。次に、アプリケーションは構成された (データベース) jar パスを実行し、Jar からクラスを実行します。これはjarとクラスのロードで機能しますが、本質的にこれらのjarをホットデプロイできるようにしたいと考えています。

要約すると、関数をサポートするクラスを含む JAR ファイルが必要です。実行時に Jar から (メインのループ アプリケーションから) 参照される定義済みクラス。メイン アプリケーションの実行中に JAR ファイルを変更する機能。

サードパーティのライブラリを使用する場合は、Apache Felix を使用することをお勧めします。

ありがとう

私はApache Felix 4を使用してそれを理解したと思います.これはjar/classesをロードする最良の方法ですか? または、より効率的な方法があります。これまでの私の調査では、解決策は 1 つではありませんでした。ありがとう。

    FrameworkFactory ff = new FrameworkFactory ();
     Map<String,Object> config = new HashMap<String,Object>();
      config.put("org.osgi.framework.storage", "c:\\temp\\myclientBundles");
       config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
   "packages needed,more packages needed");
  config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");

  Framework fwk = ff.newFramework(config);
  fwk.start();


  BundleContext bc = fwk.getBundleContext();

  Bundle bundle =   bc.installBundle("file:C:\\my_client.jar");


      bundle.start();
      bundle.update();
      Class clazz = bundle.loadClass("client.work.process");
      Job pc = (Job) clazz.newInstance();
      pc.startWork(someConfigObject);
      bundle.stop();
      fwk.stop();
4

2 に答える 2

2

私があなたの言うことを正しく理解しているなら、あなたはOSGiでjarを動的にロードする方法の例を求めていますね。

OSGiでは、動的にロードされるモジュールはバンドルと呼ばれます。したがって、基本的に、問題を解決するための最も一般的なアプローチは、OSGiバンドルでjarファイルを回転させることです。OSGiバンドルは、いくつかの拡張機能を備えた通常のJava jarです。他のJavaパッケージへの依存関係が宣言されているマニフェストファイル(txtファイル)があります。バンドルの開始時と停止時に呼び出されるActivatorクラス。このアクティベーターはバンドルの中心部分であり、バンドルの他の部分をインスタンス化する方法を知っています。

これで、動的jarが単なるライブラリjarであり、そのjavaパッケージのみをシステムに提供したい場合は、単純なマニフェストファイルを追加するだけで、アクティベーターなしで実行することもできます。自動的に変換を行うことができるツールもあります-BNDを確認してください。

次に、バンドルの準備ができたら、installコマンドを使用して、任意のOSGiフレームワークに動的にバンドルをインストールできます。リロードは、updateコマンドなどを呼び出すことによって行われます。ライフサイクルは非常に明確に定義されており、車輪の再発明の代わりにこれを使用することを強くお勧めします;)

いくつかの例とデモについては、こちらをご覧ください

お役に立てれば。

于 2012-07-18T09:52:24.297 に答える
2

さて、簡単に言うと、あなたの問題がクラスをロードしているとは信じられません... :-)クラスをロードするために解決できると思う別の問題があると思いますか?

単純にクラスのロードを開始するほとんどの場合、問題は拡張性です。彼らはシステムを持っていて、それを新しい機能で選択的に拡張したいと考えています。プロバイダー jar を更新したいので、同様の問題があると思いますか?

その場合は、bndtools をダウンロードして OSGi サービスを調べてください。通常、これらのサービスは非常にうまく適合します。

さて、更新後。私があなたのことをよく理解していれば、Apache Felix と Apache Felix File Install を十分に活用できるでしょう。File Install はディレクトリを監視し、フレームワーク内のそのディレクトリにバンドルをインストールします。ディレクトリからその jar を削除すると、バンドルがアンインストールされます。(私は 12 年以上前にファイル インストールの原型を書きました!)

メイン JAR の場合、次のようにします。

@Component(immediate=true)
public void Main {  
    @Reference
    void setClient( Client client) { ... } // called whenever a client gets started
}

各クライアント JAR について:

@Component
public void ClientImpl implements Client {
  ... whatever
}

これは、bndtools を使用するときに記述する必要がある事実上のすべてです。コンポーネント プロジェクトを作成し、メイン コード用の Bundle Descriptor とクライアント コード サンプル用の任意の数の記述子を追加してから、Run As -> OSGi Run を選択するだけです。次に、Apache Felix File Install をダウンロードし、これを実行タブに追加して、他のプロジェクトを作成し、jar ファイル (生成されたフォルダーに継続的に作成されます) をファイル インストール フォルダーにドロップします。これよりずっと簡単にはなりません:-)

于 2012-07-19T13:58:38.390 に答える