Perché ricevo un NoClassDefFoundError in Java?


530

Ricevo un NoClassDefFoundErrorquando eseguo la mia applicazione Java. Qual è in genere la causa di questo?


1
Credo che possa succedere anche se non esegui il tuo programma Java con la sintassi corretta. Ad esempio, devi chiamare la tua classe dalla cartella bin principale con il nome completo del pacchetto (es. My.package.myClass). Sarei più specifico se potessi ma non sono un gran tipo di java. Ricordo solo di averlo incasinato un paio di volte.
Frank Hadder,

17
@BoltClock Abbiamo bisogno di una domanda canonica a cui puntare i numerosi duplicati. Perché non può essere?
Raedwald,

21
Hai mai pensato di cambiare la risposta accettata in modo che quella che la community trova più preziosa sia in cima?
Martin Smith,

Risposte:


264

Ciò è causato quando esiste un file di classe da cui dipende il codice ed è presente in fase di compilazione ma non trovato in fase di esecuzione. Cerca le differenze nei tempi di compilazione e nei percorsi delle classi di runtime.


1
Ho riscontrato questo errore durante l'inserimento di un file di origine nello spazio dei nomi / pacchetto errato. Ho pensato che avrei potuto metterlo ovunque, e il compilatore era felice. Ho scoperto che avrei dovuto essere più diligente anche per il runtime per essere felice.
CenterOrbit

1
Ho avuto questo errore una volta quando il mio server ha esaurito la memoria durante il caricamento di un file. Ogni volta che ho provato il caricamento, ho ricevuto un errore diverso. Alla fine mi ha detto che non avevo abbastanza spazio sul mucchio.
James M. Lay

81
Questa risposta non è necessariamente vera e sarà fuorviante per molte persone! Vedi la risposta migliore da Jared di seguito.
Dave L.,

4
@DaveL. Grazie! La risposta di Jared con oltre 400 voti è molto al di sotto! Una risposta con -4 voti in su (in basso?) È decisamente al di sopra. C'è qualcosa di sospetto nella logica di ordinamento delle risposte di SO.
Saurabh Patil,

1
Questo è un tiro a lungo per qualcuno, ma ho riscontrato questo errore perché la classe in questione conteneva un SimpleDateFormat che era stato inizializzato con un carattere non valido (avevo T nel mezzo invece di 'T').
Ryan D,

818

Sebbene sia possibile che ciò sia dovuto a una mancata corrispondenza del percorso di classe tra tempo di compilazione e tempo di esecuzione, non è necessariamente vero.

In questo caso è importante mantenere due o tre diverse eccezioni nella nostra testa:

  1. java.lang.ClassNotFoundException Questa eccezione indica che la classe non è stata trovata sul percorso di classe. Ciò indica che stavamo tentando di caricare la definizione della classe e che la classe non esisteva sul percorso di classe.

  2. java.lang.NoClassDefFoundError Questa eccezione indica che la JVM ha cercato nella sua struttura di dati di definizione di classe interna la definizione di una classe e non l'ha trovata. Ciò è diverso dal dire che non può essere caricato dal percorso di classe. Di solito questo indica che in precedenza abbiamo tentato di caricare una classe dal percorso di classe, ma non è riuscito per qualche motivo - ora stiamo provando a utilizzare nuovamente la classe (e quindi è necessario caricarla, poiché non è riuscita l'ultima volta), ma noi ' non proveremo nemmeno a caricarlo, perché non siamo riusciti a caricarlo prima (e ragionevolmente sospettiamo che avremmo fallito di nuovo). L'errore precedente potrebbe essere ClassNotFoundException o ExceptionInInitializerError (che indica un errore nel blocco di inizializzazione statica) o qualsiasi altro numero di altri problemi. Il punto è che NoClassDefFoundError non è necessariamente un problema di percorso di classe.


30
Grazie per aver menzionato la causa di un NoClassDefFoundError, questo mi ha aiutato molto! Nel mio caso, prima era stato lanciato un ExceptionInInitializerError, ecco come ho scoperto gli errori nei blocchi statici.
Thomas,

@Jared, quando ottengo Error: Could not find or load main class, sarà classificato in quale categoria di errore?
Vikram,

@Pops: ha reso la lingua più dettagliata per specificare che gli oggetti dei verbi "provano" :)
Jared,

1
@Vikram il "Impossibile trovare o caricare la classe principale" non è un'eccezione Java, è causata dal programma di avvio (che controlla il JAR e l'attributo manifest principale).
Devo dire il

2
ClassNotFoundException viene generata anche quando una classe ha un'inizializzazione statica che genera un errore o un'eccezione. Probabilmente avrebbero dovuto scegliere un nome diverso per quell'evento.
coladict

125

Ecco il codice da illustrare java.lang.NoClassDefFoundError. Si prega di consultare la risposta di Jared per una spiegazione dettagliata.

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;
}

3
E la ragione è che dopo il primo tentativo jvm sa già che non funzionerà e lancerà una seconda eccezione diversa?
ikamen,

@ikamen Apparentemente ha archiviato da qualche parte l'inizializzazione della classe non riuscita SimpleCalculatordopo la divisione per zero? Qualcuno ha un riferimento alla documentazione ufficiale per questo comportamento?
ᴠɪɴᴄᴇɴᴛ

4
@PhilipRego Non sei sicuro di cosa intendi per NoClassDefFoundError "puro". La prima volta che new SimpleCalculator()si chiama, si ottiene un ExceptionInInitializerError con un causato da di ArithmeticException. La seconda volta che chiami new SimpleCalculator()ricevi un NoClassDefFoundError puro come un altro. Il punto è che è possibile ottenere un NoClassDefFoundError per un motivo diverso da SimpleCalculator.class che non si trova sul percorso di classe in fase di esecuzione.
Harperska,

36

NoClassDefFoundError In Java

Definizione:

  1. Java Virtual Machine non è in grado di trovare una particolare classe in fase di esecuzione che era disponibile al momento della compilazione.

  2. Se una classe era presente durante la compilazione ma non disponibile nel percorso di classe Java durante il runtime.

inserisci qui la descrizione dell'immagine

Esempi:

  1. La classe non è in Classpath, non esiste un modo sicuro per conoscerla, ma molte volte puoi semplicemente dare un'occhiata per stampare System.getproperty ("java.classpath") e stamperà il classpath da lì almeno un'idea del tuo attuale percorso di classe di runtime.
  2. Un semplice esempio di NoClassDefFoundError è la classe appartiene a un file JAR mancante o JAR non è stato aggiunto nel classpath o talvolta il nome del vaso è stato modificato da qualcuno come nel mio caso uno dei miei colleghi ha cambiato tibco.jar in tibco_v3.jar e il programma è fallendo con java.lang.NoClassDefFoundError e mi chiedevamo cosa non andasse.

  3. Prova a eseguire l'opzione esplicitamente -classpath con il percorso di classe che ritieni possa funzionare e se funziona, allora è un segno breve certo che qualcuno sta scavalcando il percorso di classe java.

  4. Il problema delle autorizzazioni sul file JAR può anche causare NoClassDefFoundError in Java.
  5. L'errore di battitura sulla configurazione XML può anche causare NoClassDefFoundError in Java.
  6. quando la classe compilata che è definita in un pacchetto, non si presenta nello stesso pacchetto durante il caricamento come nel caso di JApplet, genererà NoClassDefFoundError in Java.

Possibili soluzioni:

  1. La classe non è disponibile in Java Classpath.
  2. Se si lavora in un ambiente J2EE rispetto alla visibilità di Class tra più Classloader può anche causare java.lang.NoClassDefFoundError, vedere esempi e sezione scenari per una discussione dettagliata.
  3. Cerca java.lang.ExceptionInInitializerError nel tuo file di registro. NoClassDefFoundError a causa del fallimento dell'inizializzazione statica è abbastanza comune.
  4. Poiché NoClassDefFoundError è una sottoclasse di java.lang.LinkageError, può anche verificarsi se una di esse come la libreria nativa potrebbe non essere disponibile.
  5. Qualsiasi script di avvio ha la precedenza sulla variabile d'ambiente Classpath.
  6. Potrebbe essere in esecuzione il programma utilizzando il comando jar e la classe non è stata definita nell'attributo ClassPath del file manifest.

risorse:

3 modi per risolvere NoClassDefFoundError

java.lang.NoClassDefFoundError Pattern di problemi


1
Bella risposta. Penso di aver provato tutto ciò che suggerisci e ho ancora quel problema. Posso escluderne alcuni a causa del vaso che funziona con Spring, ma sembra non essere piaciuto a java.sql (nel mio caso il driver sap db per Hana).
JE Carter II,

In realtà si chiama System.getproperty ("java.class.path")
RIJIK

33

Ho scoperto che a volte ricevo un errore NoClassDefFound quando il codice viene compilato con una versione incompatibile della classe trovata in fase di esecuzione. L'istanza specifica che ricordo è con la libreria degli assi di Apache. C'erano in realtà 2 versioni sul mio percorso di classe runtime e stava rilevando la versione non aggiornata e incompatibile e non quella corretta, causando un errore NoClassDefFound. Questo era in un'app della riga di comando in cui stavo usando un comando simile a questo.

set classpath=%classpath%;axis.jar

Sono stato in grado di farlo prendere la versione corretta utilizzando:

set classpath=axis.jar;%classpath%;

4
Aveva lo stesso problema. Si scopre che ho compilato il file di guerra con Java7, ma la mia installazione Tomcat utilizzava Java6. Ho dovuto aggiornare le mie variabili ambientali
duvo

4
Se ciò accade, allora dirò che Java è in disordine. +2 se questo è vero. Non posso ancora verificarlo. Se trovato vero farà di nuovo + 1 (nei commenti)
supernova

7

Questa è la migliore soluzione che ho trovato finora.

Supponiamo di avere un pacchetto chiamato org.mypackagecontenente le classi:

  • HelloWorld (classe principale)
  • SupportClass
  • UtilClass

e i file che definiscono questo pacchetto sono archiviati fisicamente nella directory D:\myprogram(su Windows) o /home/user/myprogram(su Linux).

La struttura del file sarà simile a questa: inserisci qui la descrizione dell'immagine

Quando invochiamo Java, specifichiamo il nome dell'applicazione per l'esecuzione: org.mypackage.HelloWorld. Tuttavia, dobbiamo anche indicare a Java dove cercare i file e le directory che definiscono il nostro pacchetto. Quindi per avviare il programma, dobbiamo usare il seguente comando: inserisci qui la descrizione dell'immagine


6

Stavo usando Spring Framework con Maven e ho risolto questo errore nel mio progetto.

Si è verificato un errore di runtime nella classe. Stavo leggendo una proprietà come numero intero, ma quando leggeva il valore dal file delle proprietà, il suo valore era doppio.

Spring non mi ha dato una traccia completa dello stack su quale linea il runtime non è riuscito. Diceva semplicemente NoClassDefFoundError. Ma quando l'ho eseguito come un'applicazione Java nativa (eliminandolo da MVC), ha dato ExceptionInInitializerErrorquale fosse la vera causa e quale sia il modo in cui ho rintracciato l'errore.

La risposta di @ xli mi ha dato un'idea di cosa potrebbe esserci di sbagliato nel mio codice.


1
La stessa cosa mi è successa durante la programmazione di un Servlet (in NoClassDefFoundErrorrealtà è stato causato da ExceptionInInitalizerError, che è stato causato da DateTimeParseException). È un po 'fuorviante, vero? So che probabilmente avevano i loro motivi per renderlo così, ma sarebbe stato così bello avere almeno un piccolo suggerimento, che NoClassDefFoundErrorera il risultato di un'altra eccezione, senza la necessità di dedurlo. Lanciare di ExceptionInInitializerErrornuovo sarebbe molto più chiaro. A volte la connessione tra i due potrebbe non essere così ovvia.
Bartłomiej Zieliński, il

5

Ottengo NoClassFoundError quando le classi caricate dal programma di caricamento classi runtime non possono accedere alle classi già caricate dal rootloader java. Poiché i diversi caricatori di classi si trovano in domini di sicurezza diversi (secondo java), jvm non consentirà di risolvere le classi già caricate dal rootloader nello spazio degli indirizzi del caricatore di runtime.

Esegui il programma con 'java -javaagent: tracer.jar [YOUR java ARGS]'

Produce un output che mostra la classe caricata e il caricatore env che ha caricato la classe. È molto utile tracciare perché una classe non può essere risolta.

// 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
Il link è morto. Prova la versione archiviata: web.archive.org/web/20131216000019/https://blogs.oracle.com/…
avgvstvs

5

Un caso interessante in cui potresti vedere molto NoClassDefFoundErrorsè quando:

  1. throwa RuntimeExceptionnel staticblocco della tua classeExample
  2. Intercettalo (o se semplicemente non importa come se fosse gettato in un caso di test )
  3. Prova a creare un'istanza di questa classe 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
    }
}

NoClassDefErrorverrà lanciato accompagnato ExceptionInInitializerErrordal blocco statico RuntimeException.


Si tratta di casi particolarmente importante quando si vede NoClassDefFoundErrorsnei vostri test di unità .

In un certo senso "condividi" l' staticesecuzione del blocco tra i test, ma l'iniziale ExceptionInInitializerErrorsarà solo in un caso di test. Il primo che utilizza la Exampleclasse problematica . Altri casi di test che utilizzano la Exampleclasse verranno semplicemente generati NoClassDefFoundErrors.


4
Questo è un consiglio davvero dannatamente utile nella vita reale. Ho appena avuto la stessa situazione con gli inizializzatori di attributi di classe. Hai una sola possibilità di vedere il problema reale nel registro. Una volta caricata la classe (o tentato comunque) è necessario riavviare tutto.
DailyFrankPeter

4

La tecnica di seguito mi ha aiutato molte volte:

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

dove TheNoDefFoundClass è la classe che potrebbe essere "persa" a causa di una preferenza per una versione precedente della stessa libreria utilizzata dal programma. Questo accade più frequentemente con i casi, quando il software client viene distribuito in un contenitore dominante, armato con i suoi propri classloader e tonnellate di versioni antiche delle librerie più popolari.



1

Ho risolto il mio problema disabilitando le preDexLibraries per tutti i moduli:

dexOptions {
        preDexLibraries false
        ...

1

NoClassDefFoundErrorpuò verificarsi anche quando un inizializzatore statico tenta di caricare un pacchetto di risorse che non è disponibile in runtime, ad esempio un file delle proprietà che la classe interessata tenta di caricare dalla META-INFdirectory, ma non è presente. Se non catturi NoClassDefFoundError, a volte non sarai in grado di vedere la traccia dello stack completo; per ovviare a questo problema puoi usare temporaneamente una catchclausola per 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);
}

Questo non è corretto Una risorsa mancante non ti darà questo errore. Lo otterrai solo se manca una classe .
Stephen C

@StephenC Forse dovrei enfatizzare maggiormente quella parte, ma ho scritto for example a properties file that the affected class tries to load from the META-INF directory. Questo è effettivamente successo a me e sono stato in grado di risolvere NoClassDefFoundErroraggiungendo il file delle proprietà mancante. Ho aggiunto questa risposta esattamente perché non ci si aspetterebbe questo errore nelle circostanze menzionate.
ᴠɪɴᴄᴇɴᴛ

1
Allora hai perso qualcosa di molto importante nella tua spiegazione, perché l'unico modo in cui un file di risorse mancante potrebbe innescare tale eccezione è se stai tentando di caricare il file di risorse in staticun'inizializzazione ... che ha innescato un'eccezione non controllata e ha causato l'iniz fallire. Qualsiasi eccezione non controllata che si propaga dall'inizializzazione statica lo farebbe.
Stephen C,

Se mi sbaglio (cioè questo non è dovuto a staticun'inizializzazione fallita ), sarei interessato a vedere un esempio reale (cioè un MCVE) che dimostra il comportamento.
Stephen C,

1
@StephenC Hai perfettamente ragione, però :( Ho cercato il caso in cui ho riscontrato questo problema e in effetti si trattava di un inizializzatore statico che cercava di caricare un pacchetto di risorse. Aumenterò / correggerò la mia descrizione della causa. Grazie per aver segnalato questo fuori.
ᴠɪɴᴄᴇɴᴛ

1

Ho ricevuto questo errore quando ho aggiunto la dipendenza Maven di un altro modulo al mio progetto, il problema è stato finalmente risolto aggiungendo -Xss2mall'opzione JVM del mio programma (è un megabyte di default dal JDK5.0). Si ritiene che il programma non abbia abbastanza stack per caricare la classe.


0

Se qualcuno viene qui a causa di un java.lang.NoClassDefFoundError: org/apache/log4j/Loggererrore, nel mio caso è stato prodotto perché ho usato log4j 2 (ma non ho aggiunto tutti i file che ne derivano) e alcune librerie di dipendenze hanno usato log4j 1. La soluzione era aggiungere Log4j 1.x bridge: il barattolo log4j-1.2-api-<version>.jarfornito con log4j 2. Ulteriori informazioni sulla migrazione di log4j 2 .


0

Due copie di checkout diverse per lo stesso progetto

Nel mio caso, il problema era l'incapacità di Eclipse di distinguere tra due diverse copie dello stesso progetto. Ne ho uno bloccato sul trunk (controllo versione SVN) e l'altro che lavora in un ramo alla volta. Ho provato un cambiamento nella copia di lavoro come test case di JUnit, che includeva l'estrazione di una classe interna privata per essere una classe pubblica da sola e mentre funzionava, apro l'altra copia del progetto per guardarmi attorno parte del codice che necessitava di modifiche. Ad un certo punto, ilNoClassDefFoundError spuntati lamentandosi che la classe interna privata non c'era; facendo doppio clic nella traccia dello stack mi ha portato al file di origine nella copia del progetto errata.

Chiudendo la copia del tronco del progetto ed eseguendo nuovamente il test case è stato eliminato il problema.


0

Questo errore può essere causato da requisiti di versione Java non controllati .

Nel mio caso sono stato in grado di risolvere questo errore, mentre costruivo un progetto open source di alto profilo, passando da Java 9 a Java 8 usando SDKMAN! .

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

Quindi eseguire un'installazione pulita come descritto di seguito.


Quando si utilizza Maven come strumento di compilazione, a volte è utile - e di solito gratificante, eseguire una build di 'installazione' pulita con i test disabilitati .

mvn clean install -DskipTests

Ora che tutto è stato creato e installato, puoi andare avanti ed eseguire i test.

mvn test


0

Potrebbe anche essere perché si copia il file di codice da un IDE con un determinato nome di pacchetto e si desidera provare a eseguirlo utilizzando il terminale. Dovrai prima rimuovere il nome del pacchetto dal codice. Questo succede a me


0

Nel mio caso ho riscontrato questo errore a causa di una mancata corrispondenza nelle versioni JDK. Quando ho provato a eseguire l'applicazione da Intelij non funzionava, ma funzionava dalla riga di comando. Ciò è dovuto al fatto che Intelij stava tentando di eseguirlo con Java 11 JDK configurato, ma sulla riga comandi era in esecuzione con Java 8 JDK. Dopo aver cambiato l'impostazione in File> Struttura del progetto> Impostazioni del progetto> Project SDK, ha funzionato per me.


0

Tutti parlano qui di alcune cose di configurazione Java, problemi di JVM ecc., Nel mio caso l'errore non era affatto correlato a questi argomenti e aveva un motivo molto banale e facile da risolvere: avevo un'annotazione errata sul mio endpoint nel mio controller ( Applicazione Spring Boot).


0

Ho avuto un problema interessante con NoClassDefFoundError in JavaEE che funziona con il server Liberty. Stavo usando gli adattatori di risorse IMS e il mio server.xml aveva già un adattatore di risorse per imsudbJXA.rar. Quando ho aggiunto un nuovo adattatore per imsudbXA.rar, vorrei iniziare a ottenere questo errore per gli oggetti di istanza per DLIException, IMSConnectionSpec o SQLInteractionSpec. Non riuscivo a capire perché, ma l'ho risolto creando un nuovo server.xml per il mio lavoro usando solo imsudbXA.rar. Sono sicuro che l'utilizzo di più adattatori di risorse in server.xml va bene, non ho avuto il tempo di esaminarlo.


-1

Java non è riuscito a trovare la classe A in runtime. La classe A faceva parte del progetto Maven ArtClient di un'area di lavoro diversa. Così ho importato ArtClient nel mio progetto Eclipse. Due dei miei progetti utilizzavano ArtClient come dipendenza. Ho cambiato il riferimento della libreria al riferimento del progetto per questi (Build Path -> Configure Build Path).

E il problema è andato via.


-1

Ho avuto lo stesso problema ed ero disponibile per molte ore.

Ho trovato la soluzione Nel mio caso, c'era il metodo statico definito a causa di ciò. La JVM non può creare un altro oggetto di quella classe.

Per esempio,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

-6

Ho ricevuto questo messaggio dopo aver rimosso due file dalla libreria SRC e quando li ho riportati ho continuato a vedere questo messaggio di errore.

La mia soluzione era: riavviare Eclipse. Da allora non ho più visto questo messaggio :-)


4
Ciò è spiegato dalla risposta più votata, quando hai compilato per la prima volta, i file erano lì, quindi hai rimosso alcuni file, le classi sono state eliminate, quindi in fase di esecuzione hai ottenuto ClassNotFound, quindi li hai riattivati, ma Eclipse no notare che le classi generate erano ancora mancanti, ma dopo aver riavviato Eclipse, lo spazio di lavoro è stato aggiornato e le classi erano di nuovo disponibili, ma in generale questa non è una soluzione o soluzione alternativa, la soluzione sta trovando quale classe / jar manca nel runtime classpath.
Jose Manuel Gomez Alvarez,

-7

Assicurati che corrisponda nel module:appe module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }

3
In che modo la tua soluzione è in qualche modo rilevante per questo problema comune?
Taavi Ilves,

La configurazione di esempio non è bilanciata (tre {se due }). Puoi aggiustarlo?
Peter Mortensen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.