java.lang.NoClassDefFoundError: impossibile inizializzare la classe XXX


165
public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderè una mia classe. La classe risiede nello stesso file JAR della classe principale. Quindi ciò non dovrebbe essere perché manca qualsiasi JAR dal percorso di classe.

Quando guardo il file JAR jar tf myjarfile, posso vedere l' PropHolder.classelenco lì.

A proposito: il codice funziona alla perfezione sul mio computer locale. Ma non funzionava quando lo distribuivo con alcuni script su un server Linux. Quindi penso che non sia il problema del codice. Ma per qualche motivo. il processo di distribuzione è molto difficile da tracciare.

Quale potrebbe essere il problema?


La struttura di directory appropriata nel tuo vaso corrisponde al pacchetto di classe?
Giovanni B,

bisogno di vedere qualche fonte, molte cose possono causare questo. per esempio, un'istruzione 'pacchetto' ma il file non risiede effettivamente nel percorso corrispondente
jcomeau_ictx

3
Una causa è un'eccezione durante l'inizializzazione: c'è qualche altro errore?
Michael Brewer-Davis,

Risposte:


211

La mia scommessa migliore è che c'è un problema qui:

static {
    //code for loading properties from file
}

Sembrerebbe che si sia verificata un'eccezione non rilevata e propagata fino al ClassLoader effettivo nel tentativo di caricare la classe. Avremmo bisogno di uno stacktrace per confermare questo però.

Ciò o si è verificato durante la creazione della PropHolder.propvariabile statica.


Ho dovuto affrontare lo stesso problema più volte. Sono sicuro che è a causa del staticproblema. Cosa bisogna fare per risolvere il problema?
vipera

1
Dovrai identificare quale eccezione viene generata dal staticblocco. Per eseguire il debug, metti un try/catch(Exception e)intorno all'intero blocco e registra l'eccezione. Dovrai correggere quell'eccezione. In genere l'eccezione verrà registrata, ma potrebbe essere difficile da trovare poiché viene registrata durante il caricamento di classe che può verificarsi molto presto
John Vint,

Sì, ho mantenuto il codice in try catchblocco e diceva Failed to initialize ClassA. Penso che sia il problema di JVM. Ho riavviato il mio sistema e poi tutto ha funzionato bene. Come posso risolvere questo problema in futuro senza riavviare il mio sistema e risolvere il problema con una semplice soluzione.
vipera

Impossibile inizializzare ClassA è un effetto collaterale di qualcos'altro. Ti consigliamo di guardare causese disponibile. A NoClassDefFoundErrorè sempre associato a un altro errore, dovrai cercarlo nei registri o provare a registrarlo in modo più appropriato (come forzare la registrazione in un nuovo file sul file system)
John Vint

Sarebbe più facilmente rintracciabile se Java generasse un errore CouldNotInitializeStaticPartOfClassError o qualcosa del genere. Quindi noi sviluppatori sapremmo dove cercare.
Maarten,

126

Stai ricevendo un segno java.lang.NoClassDefFoundErrorche NON significa che la tua classe sia mancante (in tal caso otterrai un java.lang.ClassNotFoundException). ClassLoader ha riscontrato un errore durante la lettura della definizione della classe durante il tentativo di leggere la classe.

Metti un tentativo / catch all'interno dell'inizializzatore statico e osserva l'eccezione. Se leggi alcuni file lì e differisce dal tuo ambiente locale è molto probabilmente la causa del problema (forse il file non può essere trovato, nessuna autorizzazione ecc.).


1
un chiarimento è che anche se NoClassDefFoundError non implica una ClassNotFoundException, è comunque una possibile causa di NoClassDefFoundError.
John Vint,

1
se avessi una ClassNotFoundException, ClassLoader non potrebbe / non potrebbe mai provare a caricare la classe, giusto?
jeha,

4
Una classe può caricare un'altra classe che non è stata trovata. La causa in quel caso è ancora una ClassNotFoundException
John Vint,

1
Avrei dovuto chiarire, intendevo solo un'eccezione .getCause ()
John Vint,

1
Questo è stato davvero utile qui, dal momento che ho impiegato circa 20 minuti a verificare che il JAR (la classe riportata appartiene) sia incluso. Una volta capito che sto guardando nella direzione sbagliata, ho capito facilmente che probabilmente mancano alcune classi di annotazioni e voilà, quella dichiarata è stata dichiarata come @Stateless, quindi ho appena aggiunto la dipendenza corrispondente e sono stato in grado di procedere ulteriormente. Grazie per il consiglio!
RAM237,

33

NoClassDefFoundError non fornisce molti indizi su cosa sia andato storto all'interno del blocco statico. È buona norma avere sempre un blocco come questo all'interno del codice di inizializzazione {...} statico:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}

Come fare questo in kotlin?
Marlon,

Grazie per aver dato il suggerimento. Nel mio caso stavo ottenendo NPE sull'inizializzazione della linea statica.
Abhishek,

3

Ho avuto la stessa eccezione, ecco come ho risolto il problema:

presupposti:

  1. Classe Junit (e test), che ha esteso un'altra classe.

  2. ApplicationContext inizializzato utilizzando spring, che avvia il progetto.

  3. Il contesto dell'applicazione è stato inizializzato nel metodo @Before

Soluzione:

Iniziare il contesto dell'applicazione dal metodo @BeforeClass, poiché la classe padre ha richiesto anche alcune classi inizializzate dal contesto dell'applicazione.

Spero che questo possa aiutare.


2

Come accennato in precedenza, questo potrebbe essere un numero di cose. Nel mio caso avevo una variabile inizializzata staticamente che si basava su una voce mancante nel mio file delle proprietà. Aggiunta la voce mancante al file delle proprietà e il problema è stato risolto.


1

Solo diversi giorni fa, ho incontrato la stessa domanda proprio come la tua. Tutto il codice funziona bene sul mio computer locale, ma risulta errore (noclassdeffound & inizializza). Quindi inserisco la mia soluzione, ma non so perché, ho semplicemente avanzato una possibilità. Spero che qualcuno sappia spiegarlo. @ John Vint In primo luogo, ti mostrerò il mio problema. Il mio codice ha variabili statiche e blocco statico entrambi. Quando ho incontrato questo problema per la prima volta, ho provato la soluzione di John Vint e ho cercato di cogliere l'eccezione. Tuttavia, non ho preso nulla. Quindi ho pensato che fosse perché la variabile statica (ma ora so che sono la stessa cosa) e ancora non ho trovato nulla. Quindi, provo a trovare la differenza tra la macchina linux e il mio computer. Poi ho scoperto che questo problema si verifica solo quando diversi thread vengono eseguiti in un processo (A proposito, la macchina Linux ha doppi core e doppi processi). Ciò significa che se ci sono due attività (entrambe usano il codice con blocco statico o variabili) eseguite nello stesso processo, va storto, ma se vengono eseguite in processi diversi, entrambe vanno bene. Nella macchina Linux, io uso

mvn -U clean  test -Dtest=path 

per eseguire un'attività, e poiché la mia variabile statica è avviare un contenitore (o forse si inizializza un nuovo classloader), quindi rimarrà fino alla fine di jvm e jvm si fermerà solo quando tutte le attività in un processo si fermano. Ogni attività avvia un nuovo contenitore (o classloader) e confonde jvm. Di conseguenza, si verifica l'errore. Quindi, come risolverlo? La mia soluzione è aggiungere un nuovo comando al comando maven e fare in modo che ogni attività vada nello stesso contenitore.

-Dxxx.version=xxxxx #sorry can't post more

Forse hai già risolto questo problema, ma spero ancora che possa aiutare altri che incontrano lo stesso problema.


Inoltre, quando il codice viene eseguito sulla macchina linux, segui l'errore sopra, c'è un altro problema: java.lang.ExceptionInInitializerError: nullsignifica che non riesce a trovare la classe nel classloader o che non sa caricare quale (suppongo). L'hai incontrato?
MonkeyKing,

1

Ho avuto la stessa eccezione - ma solo durante l'esecuzione in modalità debug, è così che ho risolto il problema (dopo 3 giorni interi): in build.gradle ho avuto: "multiDexEnabled true" impostato nella sezione defaultConfig.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

ma apparentemente questo non era abbastanza. ma quando ho cambiato:

public class MyAppClass  extends Application 

per:

public class MyAppClass  extends MultiDexApplication 

questo risolto. spero che questo possa aiutare qualcuno


0

Se stai lavorando a un progetto Android, assicurati di non chiamare alcun metodo statico su nessuna classe Android. Sto solo usando JUnit + Mockito, quindi forse alcuni altri framework potrebbero aiutarti a evitare del tutto il problema, non ne sono sicuro.

Il mio problema era chiamare Uri.parse(uriString)come parte di un inizializzatore statico per un unit test. La classe Uri è un'API Android, motivo per cui la build di unit test non è riuscita a trovarla. Ho cambiato questo valore in nullinvece e tutto è tornato alla normalità.


0

Ho avuto gli stessi problemi :java.lang.NoClassDefFoundError: Impossibile inizializzare la classe com.xxx.HttpUtils

static {
    //code for loading properties from file
}

è il problema ambientale. Ciò significa che le proprietà in application.yml sono errate o vuote!


0

Ho riscontrato lo stesso problema. Ho inserito un oggetto bean in blocco statico come di seguito:

static {
    try{
        mqttConfiguration = SpringBootBeanUtils.<MqttConfiguration>getBean(MqttConfiguration.class);
    }catch (Throwable e){
        System.out.println(e);
    }
 }

Solo perché il processo con cui il mio bean obejct inition ha causato un NPE, ho problemi. Quindi penso che dovresti controllare attentamente il tuo blocco di codice statico.

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.