私は得ています NoClassDefFoundError
、私は私のJavaアプリケーションを実行したとき。通常、これの原因は何ですか?
私は得ています NoClassDefFoundError
、私は私のJavaアプリケーションを実行したとき。通常、これの原因は何ですか?
回答:
これは、コードが依存するクラスファイルがあり、コンパイル時に存在するが実行時に見つからない場合に発生します。ビルド時間とランタイムクラスパスの違いを探します。
これはコンパイル時と実行時のクラスパスの不一致が原因である可能性がありますが、必ずしもそうではありません。
この場合、2つまたは3つの異なる例外を頭の中でまっすぐに保つことが重要です。
java.lang.ClassNotFoundException
この例外は、クラスがクラスパスで見つからなかったことを示します。これは、クラス定義をロードしようとしていて、クラスパスにクラスが存在しなかったことを示しています。
java.lang.NoClassDefFoundError
この例外は、JVMがそのクラス定義の内部クラス定義データ構造を調べ、それが見つからなかったことを示しています。これは、クラスパスからロードできなかったということとは異なります。通常、これは以前にクラスパスからクラスをロードしようとしたが、なんらかの理由で失敗したことを示します。今度はクラスを再度使用しようとしています(したがって、前回失敗したため、クラスをロードする必要があります)が、先にロードに失敗したため(そして再び失敗するのではないかと疑われているため)、ロードしようとはしません。以前の失敗は、ClassNotFoundExceptionまたはExceptionInInitializerError(静的な初期化ブロックの失敗を示す)またはその他の問題である可能性があります。ポイントは、NoClassDefFoundErrorは必ずしもクラスパスの問題ではないということです。
Error: Could not find or load main class
、それはエラーのどのカテゴリに分類されますか?
これが説明するコード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;
}
SimpleCalculator
ゼロ除算後の失敗したクラス初期化がどこかに保存されているようです?誰かがこの動作の公式ドキュメントを参照していますか?
new SimpleCalculator()
呼び出されたときに、ArithmeticExceptionの原因によるExceptionInInitializerErrorが発生します。2回目に呼び出すnew SimpleCalculator()
と、他と同じくらい純粋なNoClassDefFoundErrorが返されます。ポイントは、SimpleCalculator.classが実行時にクラスパス上にないこと以外の理由でNoClassDefFoundErrorを取得できることです。
JavaのNoClassDefFoundError
定義:
Java仮想マシンは、コンパイル時に使用可能だった実行時に特定のクラスを見つけることができません。
コンパイル時にクラスが存在したが、実行時にJavaクラスパスで使用できなかった場合。
例:
NoClassDefFoundErrorの簡単な例は、クラスが欠落しているJARファイルに属しているか、JARがクラスパスに追加されていないか、私の同僚の1人がtibco.jarをtibco_v3.jarに変更してプログラムがjava.lang.NoClassDefFoundErrorで失敗し、何が問題なのかと思っていました。
機能すると思われるクラスパスを明示的に-classpathオプションで実行してみてください。それが機能している場合は、誰かがjavaクラスパスをオーバーライドしていることを示す簡単な兆候です。
可能な解決策:
リソース:
実行時に見つかった互換性のないバージョンのクラスを使用してコードをコンパイルすると、NoClassDefFoundエラーが発生することがあります。私が思い出す具体的な例は、Apache軸ライブラリです。私のランタイムクラスパスには実際には2つのバージョンがあり、古いバージョンと互換性のないバージョンを取得していて、正しいバージョンではなかったため、NoClassDefFoundエラーが発生していました。これは、私がこれに似たコマンドを使用していたコマンドラインアプリにありました。
set classpath=%classpath%;axis.jar
私はそれを使用して適切なバージョンを取得することができました:
set classpath=axis.jar;%classpath%;
これは最高のソリューションです私がこれまでに見つけです。
org.mypackage
クラスを含むと呼ばれるパッケージがあるとします:
このパッケージを定義するファイルは、ディレクトリD:\myprogram
(Windowsの場合)または/home/user/myprogram
(Linux)の。
Javaを呼び出すときに、実行するアプリケーションの名前を指定しますorg.mypackage.HelloWorld
。ただし、パッケージを定義するファイルとディレクトリの場所をJavaに通知する必要もあります。したがって、プログラムを起動するには、次のコマンドを使用する必要があります。
MavenでSpring Frameworkを使用していて、このエラーをプロジェクトで解決しました。
クラスでランタイムエラーが発生しました。プロパティを整数として読み込んでいましたが、プロパティファイルから値を読み込んだとき、その値はdoubleでした。
Springは、ランタイムが失敗した行の完全なスタックトレースを提供しませんでした。それは単に言いましたNoClassDefFoundError
。しかし、それをネイティブJavaアプリケーションとして実行したとき(MVCから取り出したとき)、ExceptionInInitializerError
すると、どちらが本当の原因で、どちらがエラーを追跡したかがわかります。
@xliの回答から、コードのどこに問題があるのかがわかりました。
NoClassDefFoundError
実際にはが原因でExceptionInInitalizerError
、これはが原因ですDateTimeParseException
)。少し誤解を招きやすいですね。私は彼らがおそらくそのようにする理由を持っていることを知っていますが、それNoClassDefFoundError
を推論する必要なしに、少なくとも別の例外の結果であった少なくとも小さなヒントがあればとても良いでしょう。ExceptionInInitializerError
もう一度投げるだけの方がはるかにはっきりします。2つの間の接続がそれほど明白でない場合があります。
ランタイムクラスローダーによって読み込まれたクラスが、Javaルートローダーによって既に読み込まれたクラスにアクセスできない場合、NoClassFoundErrorが発生します。異なるクラスローダーは異なるセキュリティドメインにあるため(Javaによると)、jvmでは、ルートローダーによって既にロードされているクラスをランタイムローダーのアドレス空間で解決できません。
「java -javaagent:tracer.jar [YOUR java ARGS]」を使用してプログラムを実行します
ロードされたクラスと、クラスをロードしたローダー環境を示す出力を生成します。クラスを解決できない理由を追跡することは非常に役立ちます。
// 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;
}
});
}
}
あなたが多く見るかもしれない1つの興味深いケースはあなたが以下のNoClassDefFoundErrors
場合です:
throw
A RuntimeException
におけるstatic
クラスのブロックExample
Example
static class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
NoClassDefError
ExceptionInInitializerError
静的ブロックから一緒にスローされますRuntimeException
。
これはNoClassDefFoundErrors
、ユニットテストに表示される場合に特に重要なケースです。。
ある意味ではstatic
、テスト間でブロックの実行を「共有」しますが、イニシャルExceptionInInitializerError
は1つのテストケースに含まれます。問題のあるExample
クラスを使用する最初のもの。Example
クラスを使用する他のテストケースは単にスローしNoClassDefFoundErrors
ます。
コード(EMFなど)を生成した場合、すべてのスタック領域を消費する静的イニシャライザが多すぎる可能性があります。
Stack Overflowの質問を参照してください。Javaスタックサイズを増やす方法は?。
NoClassDefFoundError
静的イニシャライザがランタイムで利用できないリソースバンドルをロードしようとしたときにも発生する可能性があります。たとえば、影響を受けるクラスがMETA-INF
ディレクトリからロードしようとしたがそこにないプロパティファイルなどです。キャッチしNoClassDefFoundError
ないと、完全なスタックトレースを表示できないことがあります。これを克服するには、次のcatch
句を一時的に使用できますThrowable
。
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
。これは実際に私に起こりNoClassDefFoundError
、欠落しているプロパティファイルを追加することで解決できました。上記の状況下ではこのエラーを予期しないため、この回答を正確に追加しました。
static
初期化でリソースファイルをロードしようとした場合にのみ、説明で非常に重要な何かを見落としました。これにより、チェックされない例外がトリガーされ、クラスが初期化されました。失敗する。静的な初期化から伝播する未チェックの例外があればそれを行います。
static
初期化の失敗が原因ではない場合)、動作を示す実際の例(MCVEなど)を参照してください。
私の場合、問題はEclipseが同じプロジェクトの2つの異なるコピーを区別できないことでした。私は1つをトランク(SVNバージョン管理)でロックし、もう1つは一度に1つのブランチで作業しています。私はJUnitテストケースとして、作業コピーの1つの変更を試しました。これには、プライベート内部クラスをそれ自体でパブリッククラスとして抽出することが含まれ、それが機能している間に、プロジェクトのもう1つのコピーを開いて、他のいくつかを見回しました。変更が必要なコードの一部。ある時点で、NoClassDefFoundError
プライベート内部クラスがそこにないという不満がポップアップしました。スタックトレースをダブルクリックすると、間違ったプロジェクトコピーのソースファイルが表示されました。
プロジェクトのトランクコピーを閉じてテストケースを再度実行すると、問題は解消されました。
このエラーは、Javaバージョンの要件がチェックされていないことが原因である可能性があります。
私の場合、SDKMANを使用してJava 9からJava 8に切り替えることで、注目度の高いオープンソースプロジェクトを構築しているときにこのエラーを解決できました。。
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
次に、以下の説明に従ってクリーンインストールを実行します。
ビルドツールとしてMavenを使用する場合、テストを無効にしてクリーンな「インストール」ビルドを行うと役立つことがあります。
mvn clean install -DskipTests
今すぐことすべてが構築され、インストールされている、あなたは先に行くと、テストを実行することができます。
mvn test
プロジェクトのJavaビルドパスの[順序とエクスポート]タブでクラスをエクスポートしないと、NoClassDefFoundエラーが発生しました。プロジェクトのビルドパスに追加する依存関係の[注文とエクスポート]タブに必ずチェックマークを付けてください。Eclipse警告を参照してください:XXXXXXXXXXX.jarはエクスポートまたは公開されません。実行時ClassNotFoundExceptionsが発生する可能性があります。
私の場合、エラーはこれらのトピックとはまったく関係がなく、非常に些細で簡単に解決できる理由がありました:コントローラーのエンドポイントに間違った注釈がありました( Spring Bootアプリケーション)。
Libertyサーバーで動作するJavaEEのNoClassDefFoundErrorで興味深い問題が発生しました。私はIMSリソースアダプタを使用していましたが、server.xmlにはすでにimsudbJXA.rar用のリソースアダプタがありました。imsudbXA.rarの新しいアダプタを追加すると、DLIException、IMSConnectionSpec、またはSQLInteractionSpecのインスタンスオブジェクトでこのエラーが発生し始めます。理由はわかりませんが、imsudbXA.rarのみを使用して作業用に新しいserver.xmlを作成することで解決しました。server.xmlで複数のリソースアダプターを使用することは問題ないと確信しています。
SRCライブラリから2つのファイルを削除した後にこのメッセージが表示され、それらを元に戻したときに、このエラーメッセージが何度も表示されました。
私の解決策は、Eclipseを再起動することでした。それ以来、このメッセージはもう見ていません:-)
中に必ずこのマッチを行いますmodule:app
とmodule:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
と2 }
)。直せますか?