Ricevo un NoClassDefFoundError
quando eseguo la mia applicazione Java. Qual è in genere la causa di questo?
Ricevo un NoClassDefFoundError
quando eseguo la mia applicazione Java. Qual è in genere la causa di questo?
Risposte:
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.
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:
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.
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.
Error: Could not find or load main class
, sarà classificato in quale categoria di errore?
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;
}
SimpleCalculator
dopo la divisione per zero? Qualcuno ha un riferimento alla documentazione ufficiale per questo comportamento?
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.
NoClassDefFoundError In Java
Definizione:
Java Virtual Machine non è in grado di trovare una particolare classe in fase di esecuzione che era disponibile al momento della compilazione.
Se una classe era presente durante la compilazione ma non disponibile nel percorso di classe Java durante il runtime.
Esempi:
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.
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.
Possibili soluzioni:
risorse:
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%;
Questa è la migliore soluzione che ho trovato finora.
Supponiamo di avere un pacchetto chiamato org.mypackage
contenente le classi:
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:
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:
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 ExceptionInInitializerError
quale 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.
NoClassDefFoundError
realtà è 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 NoClassDefFoundError
era il risultato di un'altra eccezione, senza la necessità di dedurlo. Lanciare di ExceptionInInitializerError
nuovo sarebbe molto più chiaro. A volte la connessione tra i due potrebbe non essere così ovvia.
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;
}
});
}
}
Un caso interessante in cui potresti vedere molto NoClassDefFoundErrors
è quando:
throw
a RuntimeException
nel static
blocco della tua classeExample
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 ExceptionInInitializerError
dal blocco statico RuntimeException
.
Si tratta di casi particolarmente importante quando si vede NoClassDefFoundErrors
nei vostri test di unità .
In un certo senso "condividi" l' static
esecuzione del blocco tra i test, ma l'iniziale ExceptionInInitializerError
sarà solo in un caso di test. Il primo che utilizza la Example
classe problematica . Altri casi di test che utilizzano la Example
classe verranno semplicemente generati NoClassDefFoundErrors
.
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.
Nel caso in cui si abbia un codice generato (EMF, ecc.), Ci possono essere troppi inizializzatori statici che consumano tutto lo spazio dello stack.
Vedi domanda Stack Overflow Come aumentare le dimensioni dello stack Java? .
NoClassDefFoundError
può 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-INF
directory, 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 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);
}
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 NoClassDefFoundError
aggiungendo il file delle proprietà mancante. Ho aggiunto questa risposta esattamente perché non ci si aspetterebbe questo errore nelle circostanze menzionate.
static
un'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.
static
un'inizializzazione fallita ), sarei interessato a vedere un esempio reale (cioè un MCVE) che dimostra il comportamento.
Ho ricevuto questo errore quando ho aggiunto la dipendenza Maven di un altro modulo al mio progetto, il problema è stato finalmente risolto aggiungendo -Xss2m
all'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.
Se qualcuno viene qui a causa di un 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 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>.jar
fornito con log4j 2. Ulteriori informazioni sulla migrazione di log4j 2 .
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.
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
Ho riscontrato errori NoClassDefFound quando non ho esportato una classe nella scheda "Ordina ed esporta" nel percorso di costruzione Java del mio progetto. Assicurati di mettere un segno di spunta nella scheda "Ordina ed esporta" di tutte le dipendenze che aggiungi al percorso di costruzione del progetto. Vedi avviso Eclipse: XXXXXXXXXXX.jar non verrà esportato o pubblicato. Potrebbero verificarsi runtime ClassNotFoundExceptions .
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.
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).
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.
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.
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");
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 :-)
Assicurati che corrisponda nel module:app
e module:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
e due }
). Puoi aggiustarlo?