web-dev-qa-db-ja.com

java.lang.NoClassDefFoundError:クラスXXXを初期化できませんでした

public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderは私のクラスです。クラスはメインクラスの同じJARファイルにあります。 JARがクラスパスから欠落しているからではありません。

jar tf myjarfileでJARファイルを調べると、そこにリストされているPropHolder.classを見ることができます。

ところで:コードは私のローカルマシン上で正常に実行されています。しかし、スクリプトを使ってLinuxサーバーにデプロイするとうまくいきませんでした。だから私はそれがコードの問題ではないと思います。しかし、どういうわけか。展開プロセスを追跡するのは非常に困難です。

問題は何でしょうか。

143
Leon

私の最善の策は、ここに問題があることです。

static {
    //code for loading properties from file
}

不明な例外が発生し、クラスをロードしようとしている実際のClassLoaderまで伝播したように見えます。これを確認するには、スタックトレースが必要です。

それか、PropHolder.prop静的変数を作成するときに発生したかのいずれかです。

176
John Vint

あなたはJava.lang.NoClassDefFoundErrorを取得していますが、それはあなたのクラスが欠けているという意味ではありません(その場合あなたはJava.lang.ClassNotFoundExceptionを取得するでしょう)。クラスを読み込もうとしたときにクラス定義の読み込み中にClassLoaderがエラーになりました。

あなたの静的初期化子の中にtry/catchを入れて、例外を見てください。あなたがそこでいくつかのファイルを読み、それがあなたのローカル環境と異なるなら、それは問題の原因である可能性が非常に高いです(多分ファイルが見つからない、権限がないなど)。

108
jeha

NoClassDefFoundErrorは、静的ブロック内で何が問題になったのかについての手がかりをあまり与えません。静的{...}初期化コードの中に次のようなブロックを常に含めることをお勧めします。

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}
30
Mark Hansen

私は同じ例外を持っていました、これは私が問題を解決した方法です:

前提条件

  1. 他のクラスを拡張したJunitクラス(そしてテスト)。

  2. ApplicationContextはspringを使用して初期化され、それによってプロジェクトが開始されます。

  3. アプリケーションコンテキストは@Beforeメソッドで初期化されました

Solution:

親クラスにもアプリケーションコンテキスト内から初期化されたクラスがいくつか必要だったため、@BeforeClassメソッドからアプリケーションコンテキストを開始します。

これが役立つことを願っています。

3
KerenSi

上記のように、これはいくつかのことが考えられます。私の場合は、静的に初期化された変数を持っていましたが、それは私のプロパティファイルに存在しないエントリに依存していました。不足しているエントリをプロパティファイルに追加し、問題を解決しました。

1
TriMix

私は同じ例外を持っていました - しかしデバッグモードで実行している間だけ、これは私が問題を解決した方法です(3日後):私は持っていました: "multiDexEnabled true" defaultConfigセクションで.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

しかし、どうやらこれでは不十分でした。しかし私が変わったとき:

public class MyAppClass  extends Application 

に:

public class MyAppClass  extends MultiDexApplication 

これで解決しました。これが誰かに役立つことを願っています

1
Elad

Androidプロジェクトで作業している場合は、Androidクラスの静的メソッドを呼び出さないでください。私はJUnit + Mockitoを使っているだけなので、他のフレームワークで問題を完全に回避できる可能性があります。

私の問題は、単体テストの静的初期化子の一部としてUri.parse(uriString)を呼び出すことでした。 UriクラスはAndroid APIなので、単体テストでは見つけることができませんでした。代わりにこの値をnullに変更したところ、すべて正常に戻りました。

0
lifeson106

ほんの数日前、私はあなたと同じ質問に出会いました。すべてのコードは私のローカルマシンではうまく動きますが、エラーになります(noclassdeffound&initialize)。それで私は私の解決策を投稿しますが、私はその理由を知りません、私は単に可能性を進めます。誰かがこれを説明することを願っています@ John Vintまず、私はあなたに私の問題をお見せします。私のコードは静的変数と静的ブロックの両方を持っています。私が最初にこの問題に遭遇したとき、私はJohn Vintの解決策を試してみて、その例外を見つけようとしました。しかし、私は何もつかまえなかった。だから私はそれが静的変数(しかし今私はそれらが同じものであることを知っている)とまだ何も見つからないためだと思いました。だから、私はLinuxマシンと私のコンピュータの違いを見つけようとしています。それから私はこの問題が複数のスレッドが1つのプロセスで実行されるときにだけ起こることを発見しました(ところで、linuxマシンは二重コアと二重プロセスを持っています)。つまり、同じプロセス内で2つのタスク(両方とも静的ブロックまたは変数を含むコードを使用)が実行されていると、問題は発生しますが、異なるプロセスで実行されても問題はありません。 Linuxマシンでは、

mvn -U clean  test -Dtest=path 

私の静的変数はコンテナを起動するため(あるいは新しいクラスローダを初期化するため)、jvmが停止するまで保持され、jvmは1つのプロセス内のすべてのタスクが停止したときにのみ停止します。すべてのタスクは新しいコンテナ(またはクラスローダ)を起動し、jvmを混乱させます。その結果、エラーが発生します。それで、それをどのように解決しますか?私の解決策は、mavenコマンドに新しいコマンドを追加し、すべてのタスクを同じコンテナに移動させることです。

-Dxxx.version=xxxxx #sorry can't post more

たぶんあなたはすでにこの問題を解決しているかもしれませんが、それでも同じ問題に出会う他の人々を助けることを願っています。

0
MonkeyKing