java.lang.NoClassDefFoundError: Impossible d’initialiser la classe XXX

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 est une classe à part. La classe réside dans le même fichier JAR de la classe principale. Donc, cela ne devrait pas être dû au fait que les fichiers JAR ne figurent pas dans classpath.

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

Btw: le code fonctionne bien sur ma machine locale. Mais ne pouvait pas fonctionner lorsque je le déploie avec un script sur un serveur Linux. Donc, je pense 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?

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 se soit produite et propagée jusqu’au ClassLoader réel essayant de charger la classe. Nous aurions besoin d’un stacktrace pour confirmer cela.

Soit cela ou il s’est produit lors de la création de la variable statique PropHolder.prop .

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

Mettez un try / catch dans votre initialiseur statique et observez l’exception. Si vous lisez certains fichiers là-bas et que ceux-ci diffèrent de votre environnement local, c’est probablement la cause du problème (peut-être que le fichier est introuvable, qu’il ne dispose pas d’permissions, etc.).

NoClassDefFoundError ne donne pas une idée de ce qui s’est mal passé dans le bloc statique. Il est recommandé de toujours avoir un bloc comme celui-ci dans le code d’initialisation statique {…}:

 static { try { ... your init code here } catch (Throwable t) { LOG.error("Failure during static initialization", t); throw t; } } 

J’ai eu la même exception, c’est comme ça 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é avec Spring, qui initie le projet.

  3. Le contexte d’application a été initialisé dans la méthode @Before

Solution:

Initiez le contexte d’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.

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

Il y a quelques jours, j’ai rencontré la même question que la vôtre. Tout le code fonctionne bien sur ma machine locale, mais génère une erreur (noclassdeffound & initialize). Donc, je poste ma solution, mais je ne sais pas pourquoi, je fais simplement avancer une possibilité. J’espère que quelqu’un saura l’expliquer. @ John Vint Tout d’abord, je vais vous montrer mon problème. Mon code a une variable statique et un bloc statique à la fois. Lorsque j’ai rencontré ce problème pour la première fois, j’ai essayé la solution de John Vint et j’ai tenté de détecter l’exception. Cependant, je n’ai rien attrapé. Donc j’ai pensé que c’était parce que la variable statique (mais maintenant je sais qu’ils sont la même chose) et que je n’ai toujours rien trouvé. J’essaie donc de trouver la différence entre la machine Linux et mon ordinateur. Ensuite, j’ai constaté que ce problème ne se produit que lorsque plusieurs threads sont exécutés en un seul processus (en passant, la machine Linux a des cœurs doubles et des processus doubles). Cela signifie que s’il y a 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 ne va pas, mais si elles s’exécutent dans des processus différents, les deux sont corrects. Dans la machine Linux, j’utilise

 mvn -U clean test -Dtest=path 

pour exécuter une tâche, et parce que ma variable statique doit démarrer un conteneur (ou peut-être initialiser un nouveau chargeur de classe), elle rest jusqu’à l’arrêt de jvm et le jvm s’arrête uniquement lorsque toutes les tâches d’un processus s’arrêtent. Chaque tâche démarrera un nouveau conteneur (ou classloader) et rendra le jvm confus. En conséquence, l’erreur se produit. Alors, comment le résoudre? Ma solution consiste à append une nouvelle commande à la commande maven et à faire en sorte que chaque tâche soit placée 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érez que cela aidera d’autres personnes qui rencontrent le même problème.

Si vous travaillez sur un projet Android, assurez-vous de ne pas appeler de méthodes statiques sur les classes Android. J’utilise uniquement JUnit + Mockito, alors peut-être que d’autres frameworks pourraient vous aider à éviter le problème, je n’en suis pas sûr.

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