615

NoClassDefFoundErrorJavaアプリケーションを実行するとが表示されます。通常、これの原因は何ですか?

4

30 に答える 30

955

これは、コンパイル時と実行時のクラスパスの不一致が原因である可能性がありますが、必ずしもそうではありません。

この場合、2 つまたは 3 つの異なる例外を頭に入れておくことが重要です。

  1. java.lang.ClassNotFoundException この例外は、クラスパスでクラスが見つからなかったことを示します。これは、クラス定義をロードしようとしていて、そのクラスがクラスパスに存在しなかったことを示しています。

  2. java.lang.NoClassDefFoundError この例外は、JVM が内部クラス定義データ構造でクラスの定義を探したが、見つからなかったことを示します。これは、クラスパスからロードできなかったということとは異なります。通常、これは、以前にクラスパスからクラスをロードしようとしたが、何らかの理由で失敗したことを示しています。今度はクラスを再度使用しようとしています (前回失敗したため、ロードする必要があります)。以前にロードに失敗したため、ロードしようとさえしません(そして、再び失敗する可能性が合理的に疑われます)。以前の失敗は、ClassNotFoundException または ExceptionInInitializerError (静的初期化ブロックでの失敗を示す)、またはその他のさまざまな問題である可能性があります。要点は、 NoClassDefFoundError は必ずしもクラスパスの問題ではないということです。

于 2011-04-22T15:28:27.997 に答える
288

これは、コードが依存するクラス ファイルがあり、コンパイル時には存在するが実行時には見つからない場合に発生します。ビルド時と実行時のクラスパスの違いを探します。

于 2008-08-29T15:01:07.607 に答える
140

説明するコードは次のとおりjava.lang.NoClassDefFoundErrorです。詳細な説明については、 Jared の回答を参照してください。

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}
于 2015-02-13T19:20:04.870 に答える
33

実行時に互換性のないバージョンのクラスを使用してコードをコンパイルすると、NoClassDefFound エラーが発生することがあります。私が思い出す特定のインスタンスは、Apache 軸ライブラリを使用したものです。実行時クラスパスには実際には 2 つのバージョンがあり、古いバージョンと互換性のないバージョンが選択され、正しいバージョンではなく、NoClassDefFound エラーが発生しました。これは、これに似たコマンドを使用していたコマンド ライン アプリでした。

set classpath=%classpath%;axis.jar

次を使用して、適切なバージョンを取得することができました。

set classpath=axis.jar;%classpath%;
于 2008-08-29T15:06:36.923 に答える
8

これは私がこれまでに見つけた最良の解決策です。

org.mypackageクラスを含むというパッケージがあるとします。

  • HelloWorld (メインクラス)
  • サポートクラス
  • UtilClass

このパッケージを定義するファイルは、ディレクトリD:\myprogram(Windows の場合) または/home/user/myprogram(Linux の場合) の下に物理的に保存されます。

ファイル構造は次のようになります。 ここに画像の説明を入力

Java を呼び出すときは、実行するアプリケーションの名前を指定します: org.mypackage.HelloWorld. ただし、パッケージを定義するファイルとディレクトリを探す場所を Java に伝える必要もあります。したがって、プログラムを起動するには、次のコマンドを使用する必要があります。 ここに画像の説明を入力

于 2015-09-15T18:44:29.840 に答える
5

ランタイム クラス ローダーによってロードされたクラスが、Java ルートローダーによって既にロードされているクラスにアクセスできない場合、NoClassFoundError が発生します。異なるクラス ローダーは異なるセキュリティ ドメインにあるため (java によると)、jvm は、ルートローダーによって既にロードされているクラスをランタイム ローダーのアドレス空間で解決することを許可しません。

「java -javaagent:tracer.jar [YOUR Java ARGS]」でプログラムを実行します

ロードされたクラスと、クラスをロードしたローダー env を示す出力が生成されます。クラスを解決できない理由を追跡することは非常に役立ちます。

// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

import java.lang.instrument.*;
import java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}
于 2015-09-09T12:02:32.640 に答える
4

以下のテクニックは何度も私を助けました:

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

ここで、TheNoDefFoundClass は、プログラムで使用される同じライブラリの古いバージョンを優先するために「失われる」可能性があるクラスです。これは、クライアント ソフトウェアが、独自のクラスローダーと最も人気のあるライブラリの古いバージョンを備えた支配的なコンテナーに展開されている場合に最も頻繁に発生します。

于 2016-07-27T13:44:35.437 に答える
3

生成されたコード (EMF など) がある場合、すべてのスタック領域を消費する静的初期化子が多すぎる可能性があります。

スタック オーバーフローの質問 Java スタック サイズを増やす方法を参照してください。.

于 2016-11-07T14:03:17.030 に答える
-1

私も同じ問題を抱えていて、何時間も在庫がありました。

解決策を見つけました。私の場合、そのために定義された静的メソッドがありました。JVM は、そのクラスの別のオブジェクトを作成できません。

例えば、

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
于 2016-07-14T19:46:14.580 に答える
-7

module:appこれがとで一致することを確認してくださいmodule:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }
于 2016-04-26T16:40:23.120 に答える