4

Test1 と Test2 の 2 つの Java プロジェクトがあります。Test1 には、eclipse Java ビルド パスにライブラリ lib が追加されています。Test2 には、ビルド パスに追加された jar があります。

Test1      Test2
/src        /src
lib         Referenced Libraries
 x-1.1.jar   a.jar
 y.jar        x-1.2
              z

Test1 のコードは、x-1.1.jar に依存する y.jar の関数/クラスを呼び出します。jar のソースがないため、x-1.1.jar のどの関数/クラスが y.jar で使用されているかわかりません。同様に、Test2 は、jar の x-1.2 バージョンに依存する a.jar の z パッケージの関数/クラスを呼び出します。

これで、Test1 と Test2 の両方のプロジェクトが必要な Test プロジェクトができました。

Test
/src
 Test1 code
 Test2 code
 some other code which uses Test1 as well as Test2 libraries
lib
 x-1.1.jar
 y.jar
Referenced Libraries
 a.jar
  x-1.2
  z 

Test プロジェクトを実行すると、jar-hell の状況に陥ります。ここで私の研究で使用される 2 つのアプローチは次のとおりです。

  1. クラスパス: このアプローチの問題は、Test1 と Test2 の両方のライブラリ/jar が eclipse Java ビルド パスに追加されるため、x.jar の最初にロードされたバージョンのみがアクセスされ、クラスローダーを使用しても Test2 コードが壊れることです。
  2. osgi: アプローチの問題は、プロジェクトによって参照されているものではなく、osgi バンドルから Test1 および Test2 の src フォルダー内のパッケージのみをエクスポートできることです。しかし、Test プロジェクトには、Test1 および Test2 ライブラリを使用するコードがあります。

私が十分に明確であることを願っています。どんな助けでも大歓迎です。前もって感謝します。

質問にさらに情報を追加する: 私のプロジェクトでは、異なる jar ファイルをバンドルした 2 つの異なる Java SDK を使用する必要があります。矛盾するものは次のとおりです。

jar file                     Test1 ver  Test2 ver
org.apache.commons.codecs    1.3        1.6
org.apache.commons.logging   1.1.1      1.1.1
org.apache.log4j             1.2.7      1.2.15
httpclient                   4.1.1      4.0.3   
httpcore                     4.1        4.1.4

これを行うにはどのような方法が考えられますか?

4

2 に答える 2

1

OSGIは実際にはソリューションである可能性が最も高く、それを行うには2つの方法があります。

  1. 依存する jar を osgi バンドルに変換し、エクスポートするパッケージのバージョンを定義し (単純に実際のバージョン番号を使用)、テスト プロジェクトからそれらを参照 (OSGI 方式) し、パッケージをインポートするときに必要な正確なバージョンを指定します。このようにして、ライブラリ jar ごと、およびプロジェクトごとに osgi バンドルを作成します。
  2. test1 と test2 の 2 つの osgi バンドルを作成します。必要なバージョンのライブラリを (埋め込み jar またはインラインとして) 埋め込み、依存パッケージをエクスポートしないでください。テストバンドルから test1 と test2 を自由に参照できます。それらは衝突しませんが、分離されたクラスローダー (バンドル クラスローダー スペース) に常駐します。Maven バンドル プラグインを使用して依存関係を埋め込む方法に関する情報: http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin%28BND%29-EmbedDependencyandExportPackage

この構成の強調:

<Embed-Dependency>
    *;scope=compile|runtime;inline=false
</Embed-Dependency>

BND ツールを使用して jar を osgi にラップする方法: http://java.dzone.com/articles/how-creategenerate-osgi

ちなみに、言及したライブラリのほとんど (すべてではないにしても) は既に osgi 対応である必要があるため、それらを osgi バンドルに変換する必要さえありません。ここで発生する可能性がある唯一の問題は、一部の jar が osgi と互換性がないことです (たとえば、コンテナーのクラス ローダー アーキテクチャについて想定しているものなど) が、これはまれなケースです。

于 2013-07-24T15:01:14.947 に答える
0

URLClassLoader各 に 1 つずつ、2 つの を使用してカスタム クラス ローディング メカニズムを実装することにより、OSGi のようにクラスパスの分離をエミュレートすることができますx-1.*.jar

これは一般的な考え方です:

File x1jar = new File("path/to/x-1.1.jar");
URLClassLoader x1loader = new URLClassLoader (x1ar.toURL(), this.getClass().getClassLoader());

File x2jar = new File("path/to/x-1.2.jar");
URLClassLoader x2loader = new URLClassLoader (x2ar.toURL(), this.getClass().getClassLoader());

// Test1 should look into x-1.1.jar ..
Class test1class = Class.forName("Test1", true, x1loader);

// .. Test2 should look into x-1.2.jar ..
Class test2class = Class.forName("Test2", true, x2loader);

// .. but both should see y.jar and z.jar via system class locader.

// Invoke whatever methods in testXclasses.

重要: システムのクラスパスに配置しないでください。つまり、それらを別のx-1.1.jarフォルダーに配置する必要があります。つまり、クラスのデプロイは次のようになります。x-1.2.jarlib

+ myapp
  + lib
    myapp.jar
    y.jar
    z.jar
  + sandbox
    x-1.1.jar
    x-1.2.jar

また、 Test1 / Test2 クラスを直接 (またはを使用して) 参照してはならず、クラス名 ( string 内) のみを使用してください。Test1Test1.class"Test1"

this answerthis oneを見てください。

于 2013-04-17T11:47:08.423 に答える