java.lang.NoClassDefFoundError: impossible d'initialiser 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 PropHolderest une classe à moi. La classe réside dans le même fichier JAR de la classe principale. Cela ne devrait donc pas car aucun JAR est absent du chemin de classe.

Lorsque je regarde le fichier JAR par jar tf myjarfile, je peux voir la PropHolder.classliste.

Btw: le code fonctionne bien sur ma machine locale. Mais je ne pouvais pas fonctionner lorsque je le déployais avec un script sur un serveur Linux. Je pense donc que ce n'est pas le problème du code. Mais pour une raison quelconque. le processus de déploiement est très difficile à suivre.

Quel pourrait être le problème?

Léon
la source
La structure de répertoires appropriée dans votre fichier jar correspond-elle au package de classe?
John B le
besoin de voir une source, de nombreuses choses peuvent causer cela. par exemple, une instruction 'package' mais le fichier ne résidant pas réellement dans le chemin correspondant
jcomeau_ictx
3
Une cause est une exception lors de l'initialisation - y a-t-il une autre sortie d'erreur?
Michael Brewer-Davis le

Réponses:

211

Mon meilleur pari est qu'il y a un problème ici:

static {
    //code for loading properties from file
}

Il semblerait qu'une exception non interceptée s'est produite et s'est propagée jusqu'au ClassLoader qui tente de charger la classe. Nous aurions besoin d'un stacktrace pour confirmer cela.

Soit cela, soit cela s'est produit lors de la création d' PropHolder.propune variable statique.

John Vint
la source
J'ai été confronté au même problème à maintes reprises. Je suis sûr que c'est à cause du staticproblème. Que faut-il faire pour résoudre le problème?
vipère
1
Vous devrez identifier quelle exception est levée à partir du staticbloc. Pour le déboguer, mettez un try/catch(Exception e)autour du bloc entier et enregistrez l'exception. Vous devrez corriger cette exception. En règle générale, l'exception sera enregistrée mais peut être difficile à trouver car elle est enregistrée pendant le chargement de classe, ce qui peut arriver très tôt
John Vint
Oui, j'ai gardé le code en try catchbloc et c'est dit Failed to initialize ClassA. Je pense que c'est le problème de JVM. J'ai redémarré mon système et tout a bien fonctionné. Comment résoudre ce problème à l'avenir sans redémarrer mon système et résoudre le problème avec une solution simple.
viper
Échec de l'initialisation de ClassA est un effet secondaire de quelque chose d'autre. Vous voudrez regarder le causesi disponible. A NoClassDefFoundErrorest toujours associé à une autre erreur, vous devrez le rechercher dans les journaux ou essayer de le consigner de manière plus appropriée (comme forcer la connexion dans un nouveau fichier sur le système de fichiers)
John Vint
Ce serait plus facilement traçable si Java lançait une erreur CouldNotInitializeStaticPartOfClassError ou quelque chose. Ensuite, en tant que développeur, nous saurions où chercher.
Maarten
126

Vous obtenez un java.lang.NoClassDefFoundErrorqui ne signifie PAS que votre classe est manquante (dans ce cas, vous obtiendrez un java.lang.ClassNotFoundException). Le ClassLoader a rencontré une erreur lors de la lecture de la définition de classe lors de la tentative de lecture de la classe.

Mettez un try / catch dans votre initialiseur statique et regardez l'exception. Si vous lisez des fichiers là-bas et que cela diffère de votre environnement local, c'est très probablement la cause du problème (peut-être que le fichier est introuvable, aucune autorisation, etc.).

jeha
la source
1
une clarifaction est que même si NoClassDefFoundError n'implique pas une ClassNotFoundException, c'est toujours une cause possible de NoClassDefFoundError.
John Vint le
1
buf si vous aviez une ClassNotFoundException, alors le ClassLoader n'essaierait / ne pourrait jamais essayer de charger la classe, non?
jeha le
4
Une classe peut charger une autre classe qui n'a pas été trouvée. La cause dans cette instance est toujours une ClassNotFoundException
John Vint
1
J'aurais dû clarifier, je voulais juste dire une exception.getCause ()
John Vint
1
Celui-ci a été vraiment utile ici, car j'ai passé environ 20 minutes à vérifier que le JAR (la classe signalée appartient) est inclus. Une fois que j'ai réalisé que je regardais dans la mauvaise direction, j'ai facilement compris qu'une classe d'annotation manquait probablement et voilà, celle signalée a été déclarée comme @Stateless, alors j'ai simplement ajouté la dépendance correspondante et j'ai pu continuer. Merci pour le conseil!
RAM237
33

NoClassDefFoundError ne donne pas beaucoup d'indices sur ce qui s'est mal passé à l'intérieur du bloc statique. Il est recommandé de toujours avoir un bloc comme celui-ci à l'intérieur du code d'initialisation static {...}:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}
Mark Hansen
la source
Comment faire cela dans kotlin?
Marlon
Merci d'avoir donné l'indice. Dans mon cas, je recevais NPE sur l'initialisation de la ligne statique.
Abhishek
3

J'ai eu la même exception, c'est ainsi que j'ai résolu le problème:

Conditions préalables:

  1. Classe Junit (et test), qui a étendu une autre classe.

  2. ApplicationContext initialisé à l'aide de spring, qui initie le projet.

  3. Le contexte Application a été initialisé dans la méthode @Before

Solution:

Initiez le contexte de l'application à partir de la méthode @BeforeClass, car la classe parente nécessitait également certaines classes initialisées à partir du contexte de l'application.

J'espère que cela aidera.

KerenSi
la source
2

Comme mentionné ci-dessus, cela pourrait être un certain nombre de choses. Dans mon cas, j'avais une variable initialisée statiquement qui reposait sur une entrée manquante dans mon fichier de propriétés. Ajout de l'entrée manquante au fichier de propriétés et le problème a été résolu.

TriMix
la source
1

Il y a quelques jours à peine, j'ai rencontré la même question, tout comme la vôtre. Tout le code fonctionne bien sur ma machine locale, mais s'avère une erreur (noclassdeffound & initialize). Alors je poste ma solution, mais je ne sais pas pourquoi, je ne fais qu'avancer une possibilité. J'espère que quelqu'un sait vous l'expliquera. @ John Vint Premièrement, je vais vous montrer mon problème. Mon code a une variable statique et un bloc statique à la fois. Quand j'ai rencontré ce problème pour la première fois, j'ai essayé la solution de John Vint et j'ai essayé d'attraper l'exception. Cependant, je n'ai rien attrapé. Alors j'ai pensé que c'est parce que la variable statique (mais maintenant je sais qu'ils sont la même chose) et toujours rien trouvé. Donc, j'essaye de trouver la différence entre la machine Linux et mon ordinateur. Ensuite, j'ai trouvé que ce problème ne se produit que lorsque plusieurs threads s'exécutent dans un processus (à propos, la machine Linux a des cœurs doubles et des processus doubles). Cela signifie que si deux tâches (les deux utilisent le code qui a un bloc statique ou des variables) exécutées dans le même processus, cela se passe mal, mais si elles s'exécutent dans des processus différents, les deux sont ok. Dans la machine Linux, j'utilise

mvn -U clean  test -Dtest=path 

pour exécuter une tâche, et parce que ma variable statique est de démarrer un conteneur (ou peut-être que vous initialisez un nouveau chargeur de classe), il restera jusqu'à l'arrêt du jvm, et le jvm ne s'arrête que lorsque toutes les tâches d'un processus s'arrêtent. Chaque tâche démarrera un nouveau conteneur (ou chargeur de classe) et rendra le jvm confus. En conséquence, l'erreur se produit. Alors, comment le résoudre? Ma solution est d'ajouter une nouvelle commande à la commande maven et de faire en sorte que chaque tâche aille dans le même conteneur.

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

Peut-être avez-vous déjà résolu ce problème, mais espérons toujours que cela aidera d'autres personnes qui rencontrent le même problème.

Roi Singe
la source
De plus, lorsque le code s'exécute sur la machine Linux, suivez l'erreur ci-dessus, il y a un autre problème:, java.lang.ExceptionInInitializerError: nullcela signifie que vous ne pouvez pas trouver la classe dans le chargeur de classe, ou que vous ne savez pas charger laquelle (je suppose). Avez-vous rencontré cela?
MonkeyKing
1

J'ai eu la même exception - mais seulement en cours d'exécution en mode débogage, voici comment j'ai résolu le problème (après 3 jours entiers): dans le build.gradle j'avais: "multiDexEnabled true" défini dans la section defaultConfig.

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

mais apparemment ce n'était pas suffisant. mais quand j'ai changé:

public class MyAppClass  extends Application 

à:

public class MyAppClass  extends MultiDexApplication 

cela l'a résolu. J'espère que cela aidera quelqu'un

Elad
la source
0

Si vous travaillez sur un projet Android, assurez-vous de n'appeler aucune méthode statique sur aucune classe Android. J'utilise uniquement JUnit + Mockito, donc peut-être que d'autres frameworks pourraient vous aider à éviter complètement le problème, je ne suis pas sûr.

Mon problème était d'appeler Uri.parse(uriString)dans le cadre d'un initialiseur statique pour un test unitaire. La classe Uri est une API Android, c'est pourquoi la version de test unitaire n'a pas pu la trouver. J'ai changé cette valeur à la nullplace et tout est revenu à la normale.

lifeson106
la source
0

J'ai eu les mêmes problèmes :java.lang.NoClassDefFoundError: Impossible d'initialiser la classe com.xxx.HttpUtils

static {
    //code for loading properties from file
}

c'est le problème d'environnement, cela signifie que les propriétés dans application.yml sont incorrectes ou vides!

user8503957
la source
0

Je rencontre le même problème. J'ai initié un objet bean dans un bloc statique comme ci-dessous:

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

Juste parce que le processus de mon obejct inition bean a causé un NPE, j'ai des problèmes. Je pense donc que vous devriez vérifier attentivement votre bloc de code statique.

lai nan
la source