2017-02-01 10 views
0

私はクラスAに以下のメソッドを持っています。すべてのクラスA、B、Cと、 'A'が呼び出されるメインクラスは同じjarファイルにあります。同じjarファイル内で発生するjava.lang.NoClassDefFoundErrorを解決するにはどうすればよいですか?

public class A {  
    private static void init() { 
     if (!init) { 
      synchronized (B.class) { 
       if (!init) { 
        map = C.creat(); 
        init = true; 
       } 
      } 
     } 
    } 
} 

コードが​​ブロック(ライン4番)でThrowablejava.lang.NoClassDefFoundErrorを投げています。 すべてのクラスが同じjarにあるので、実行時にクラスを見つけられない可能性があります。

私はExisting Questionの解決方法を完了しましたが、解決策が見つかりませんでした。助けてください。私は代わりに「B」のコードの一部を同期するためにstatic object/class Aを使用する場合

は、

問題を固定することができる静的初期化ブロックとクラスBの静的変数があります。私はなぜ例外に直面したのか、それをクラスBのみを使って修正する方法を知りたいのです。

+2

なぜB.classを使用して同期していますか?私はそれがベストプラクティスだとは思わない。 – duffymo

+0

Bの静的ブロックが 'A.init'メソッドを呼び出すことはできますか? – RealSkeptic

+0

jarのパッケージ構造を表示できますか?あなたはjd-guiを逆コンパイルすることができます – Optimus

答えて

0

そのコードをJARに実際にコンパイルした場合、 JARにはB.classが含まれています。それは起こることができません。

唯一のオプションは、使用しているJARが壊れています。それが含まれていると思われるものを含んでいません。

したがって、JARを確認してください。それについて何か間違っているはずです。たとえば、完全なコンテンツを表示するにはjar tf jarfile.jarを使用します。 B.classが実際に入っているかどうかを確認してください。

0

Java Appを起動している間にClassesオブジェクトまたはメタデータがクラスローダーによって読み込まれます。

上記のコードは、次の理由によりjava.lang.NoClassDefFoundErrorになることがあります。

1>上記の静的メソッドinitは、クラスAの静的ブロック内から呼び出されます。クラスBがクラスAの前にまだロードされておらず、クラスローダーがクラスオブジェクト(メタデータ)クラスBの定義を見つけることができません。

あなたはA.classにsyncronise場合クラスローダがクラスで仕事をするためには、それ

のクラスメタ参照を持っているので、あなたが遅延したクラスAでinitメソッドを呼び出すする必要がありB.classそれが動作し、クラスローダがクラスのメタ情報をロードできるようにします。 static初期化子ブロックからクラスAのinit()メソッドを呼び出さないようにしてください。

+0

正確ではありません。 'B.class'への参照は' B'の読み込みをトリガーします。それはJLSにあります。 'B.class'への参照がクラスの初期化を引き起こさないという事実もそうです。 –

0

B.classを使用する前に、Bの任意の方法または変数に言及したものはありましたか?そうでなければ、Bは、リピートせず、初期化されていません。 classリテラルへの参照は、クラスの初期化をトリガーしません。 「静的ブロック」は不適切な用語です。これは "static initializerブロック"です。それは走らなかった。

AまたはBのいずれかのメンバーを使用して、classリテラルではなく、同期させます。

関連する問題