2

私のプロジェクトでは、すべての JUnit テスト ケースが Eclipse プラグインではなく Eclipse フラグメントで記述されていることがわかりました。そして、各テスト クラスを JUnit プラグインとして実行します。私は概念についてあまり明確ではありません。私はこの概念に比較的慣れていません。

Plugins for Tests でフラグメントを使用することについて、より良い知識を得るためにググったところです。私が理解しているのは、フラグメントとホスト プラグインが同じクラス ローダーを共有しているということです。私の理解が間違っている場合は修正してください。

しかし、下の行の意味がわかりませんでした。

Eclipse プラグインでテストを作成すると、テスト クラスは別の Classloader によってロードされるため、テスト対象のクラスの非公開メソッドにはアクセスできません。

非公開メソッドにアクセスできないのはなぜですか? 上記の意味を簡単な例で理解するのに役立つ人はいますか?

4

1 に答える 1

2

これを理解するには、Java でクラスとクラスローディングが実際にどのように機能するかを理解する必要があります。「クラスパス」の観点からロードを考えることがよくありますが、これは物事がどのように機能するかを大幅に単純化したものです。多くの Java SE 環境ではこれでうまくいきますが、OSGi のようなマルチテナント環境ではさらに複雑になります。

基本的に、Java クラスのスコープは次の 3 つに限定されます。

  1. 名前
  2. パッケージ
  3. クラスローダー

myPackage.MyClass の 2 つのインスタンスを複数回 JVM にロードすることは完全に可能です。複数のクラスローダーが必要なだけです。これらのクラスは同一の .class ファイルからロードできますが、実行時には異なります。これは、次のようなコードを記述すると、多くの混乱を招く可能性があります。

MyClass c = (MyClass)obj;

を取得しClassNotFoundException: MyClassます。

クラスはパッケージに存在し、これに関連する特別な可視性ルールがあります。可視性が明示されていない型、メソッド、およびフィールドは、同じパッケージ内のすべての型に表示されます。クラスがロードされると、java.lang.reflect.Package に関連付けられ、クラスが同じ java.lang.reflect.Package インスタンスに関連付けられていることを本質的にチェックすることによって可視性ルールが解決されます。したがって、mypackage.MyClass の場合、2 つの異なるクラスローダーを使用して 2 回ロードすると、mypackage の 2 つの Package インスタンスが取得されます。

OSGi は、マルチテナント クラスのロードをサポートするように設計されています。これにより、同じ JVM でクラスまたはパッケージの 2 つの異なるバージョンを同時に持つことができます。これにより、異なるバージョンの依存関係がある場合に発生する多くの問題が解決されます。これは、バンドルごとに異なる Classloader を使用して実装されます。フラグメントは、バンドルに関連付けられており、フラグメント内のクラスが独自のクラスローダーを持つのではなく、バンドルのクラスローダーによってロードされるという点で、異なる働きをします。

これを元の質問に関連付けるために、junit テストを (フラグメントではなく) バンドルに入れる場合、クラスは別のクラスローダーによってロードされるため、java.lang.reflect の別のインスタンスに関連付けられます。 JVM がメンバーのアクセス可能性をテストするときに失敗するようにパッケージ化します。

于 2015-06-11T23:45:39.923 に答える