Domanda

Sto ricevendo un NoClassDefFoundError quando eseguo la mia applicazione Java.Qual è in genere la causa di ciò?

È stato utile?

Soluzione

Ciò si verifica quando è presente 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 nel tempo di compilazione e nei percorsi di classe di runtime.

Altri suggerimenti

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

In questo caso è importante tenere bene in testa due o tre diverse eccezioni:

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

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

Ecco il codice da illustrare java.lang.NoClassDefFoundError.Perfavore guarda 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;
}

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

set classpath=%classpath%;axis.jar

Sono riuscito a convincerlo a prendere la versione corretta utilizzando:

set classpath=axis.jar;%classpath%;

NoClassDefFoundErrore in Java

Definizione:

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

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

enter image description here

Esempi:

  1. La classe non è in Classpath, non esiste un modo sicuro per saperlo, ma molte volte puoi semplicemente dare un'occhiata a stampare System.getproperty("java.classpath") e stamperà il classpath da lì puoi almeno ottenere un'idea del tuo percorso di classe di runtime effettivo.
  2. Un semplice esempio di NoClassDefFoundError è che la classe appartiene a un file JAR mancante o JAR non è stato aggiunto nel classpath o talvolta il nome jar è 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 chiedevo cosa c'è che non va.

  3. Prova semplicemente a eseguire con l'opzione esplicitamente -classpath con il classpath che ritieni funzionerà e se funziona, è un segno sicuro che qualcuno sta sovrascrivendo il classpath Java.

  4. Anche un problema di autorizzazione sul file JAR può causare NoClassDefFoundError in Java.
  5. Un errore di battitura nella configurazione XML può anche causare NoClassDefFoundError in Java.
  6. quando la classe compilata che è definita in un pacchetto, non è presente 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 stai lavorando in un ambiente J2EE, la visibilità di Class tra più Classloader può anche causare java.lang.NoClassDefFoundError, consulta la sezione esempi e scenari per una discussione dettagliata.
  3. Verifica la presenza di java.lang.ExceptionInInitializerError nel file di registro.NoClassDefFoundError dovuto al fallimento dell'inizializzazione statica è abbastanza comune.
  4. Poiché NoClassDefFoundError è una sottoclasse di java.lang.LinkageError, può verificarsi anche se una delle sue dipendenze, come la libreria nativa, potrebbe non essere disponibile.
  5. Qualsiasi script di avvio sovrascrive la variabile di ambiente Classpath.
  6. Potresti eseguire il tuo 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 Modelli di problemi

Questo è il soluzione migliore Ho trovato finora.

Supponiamo di avere un pacchetto chiamato org.mypackage contenente le classi:

  • HelloWorld (classe principale)
  • SupportClass
  • UtiliClass

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 alla seguente:enter image description here

Quando invochiamo Java, specifichiamo il nome dell'applicazione da eseguire: org.mypackage.HelloWorld.Dobbiamo però anche dire a Java dove cercare i file e le directory che definiscono il nostro pacchetto.Quindi per avviare il programma, dobbiamo usare il seguente comando:enter image description here

stavo usando Quadro primaverile con Esperto di e 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 fornito un'analisi completa dello stack su quale linea il runtime ha fallito.Diceva semplicemente NoClassDefFoundError.Ma quando l'ho eseguito come applicazione Java nativa (estraendolo da MVC), ha ceduto ExceptionInInitializerError quale era la vera causa ed è così che ho rintracciato l'errore.

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

Ottengo NoClassFoundError quando le classi caricate dal caricatore di 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à alle classi già caricate dal rootloader di essere risolte nello spazio degli indirizzi del caricatore di runtime.

Esegui il tuo programma con 'java -javaagent:tracer.jar [IL TUO ARGS Java]'

Produce un output che mostra la classe caricata e l'ambiente del caricatore che ha caricato la classe.È molto utile tracciare il motivo per cui 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;
            }
        });
    }
}

Leggi questo soprattutto se vedi NoClassDefFoundErrors nei TEST UNITARI...


Un caso interessante di cui potresti vederne molti NoClassDefFoundErrors è quando:

  1. throw UN RuntimeException nel static blocco della tua classe Example
  2. Intercettalo (o se semplicemente non ha importanza come se fosse lanciato in a caso di prova)
  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
    }
}

NoClassDefError verrà lanciato accompagnato con ExceptionInInitializerError dal blocco statico RuntimeException.


Questo è un caso particolarmente importante quando vedi NoClassDefFoundErrors nel tuo PROVE UNITARIE.

In un certo senso stai "condividendo" il file static blocca l'esecuzione tra i test, ma l'iniziale ExceptionInInitializerError sarà solo in un caso di prova.Il primo che usa la problematica Example classe.Altri casi di test che utilizzano il file Example la classe lancerà e basta NoClassDefFoundErrors.

Nel caso in cui tu abbia generato codice (EMF, ecc.) potrebbero esserci troppi inizializzatori statici che consumano tutto lo spazio dello stack.

Vedi la domanda Stack Overflow Come aumentare la dimensione dello stack Java?.

La tecnica seguente mi ha aiutato molte volte:

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

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

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

dexOptions {
        preDexLibraries false
        ...

NoClassDefFoundError può verificarsi anche quando a statico l'inizializzatore 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 dal META-INF directory, ma non è presente.Se non prendi NoClassDefFoundError, a volte non sarai in grado di vedere l'intera traccia dello stack;per superare questo problema puoi utilizzare temporaneamente a catch clausola 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);
}

Se qualcuno viene qui a causa di java.lang.NoClassDefFoundError: org/apache/log4j/Logger errore, nel mio caso è stato prodotto perché ho usato log4j 2 (ma non ho aggiunto tutti i file forniti con esso) e alcune librerie di dipendenze hanno usato log4j 1.La soluzione era aggiungere il bridge Log4j 1.x:il vaso log4j-1.2-api-<version>.jar che viene fornito con log4j 2.Maggiori informazioni nel log4j 2 migrazione.

Due diverse copie di pagamento dello 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 della versione SVN) e l'altro che lavora in un ramo alla volta.Ho provato una modifica nella copia di lavoro come caso di test JUnit, che includeva l'estrazione di una classe interna privata per diventare una classe pubblica a sé stante e mentre funzionava, ho aperto l'altra copia del progetto per guardarne qualche altra parte del codice che necessitava di modifiche.Ad un certo punto, il NoClassDefFoundError è spuntato fuori lamentandosi del fatto che la classe privata interna non esisteva;facendo doppio clic nell'analisi dello stack mi ha portato al file sorgente nella copia del progetto sbagliata.

Chiudendo la copia del trunk del progetto ed eseguendo nuovamente il test case è stato risolto il problema.

Questo errore può essere causato da un'opzione non selezionata Versione Java requisiti.

Nel mio caso sono riuscito a risolvere questo errore, mentre costruivo un progetto open source di alto profilo, passando da Java 9 a Java 8 utilizzando 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 usa Esperto di come strumento di creazione, a volte è utile, e solitamente gratificante, fare a pulito build "installa". con test disabilitato.

mvn clean install -DskipTests

Ora che qualunque cosa è stato costruito e installato, puoi procedere ed eseguire i test.

mvn test

Ho ricevuto errori NoClassDefFound quando non ho esportato una classe nella scheda "Ordina ed esporta" nel percorso di creazione Java del mio progetto.Assicurati di inserire un segno di spunta nella scheda "Ordina ed esporta" di tutte le dipendenze che aggiungi al percorso di creazione del progetto.Vedere Avviso eclissi:XXXXXXXXXXX.jar non verrà esportato o pubblicato.Potrebbero verificarsi delle eccezioni di runtime ClassNotFoundException.

Java non è riuscito a trovare la classe A in runtime.La classe A era nel progetto Maven ArtClient da uno spazio di lavoro diverso.Quindi ho importato ArtClient nel mio progetto Eclipse.Due dei miei progetti utilizzavano ArtClient come dipendenza.Ho cambiato il riferimento alla libreria con il riferimento al progetto per questi (Percorso di creazione -> Configura percorso di creazione).

E il problema è scomparso.

Ho avuto lo stesso problema e sono rimasto in stock per molte ore.

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

Per esempio,

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

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

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

Assicurati che corrisponda nel file module:app E module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top