web-dev-qa-db-fra.com

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 à moi. La classe réside dans le même fichier JAR de la classe principale. Cela ne devrait donc pas, car aucun fichier JAR n’est présent dans Classpath.

Lorsque je regarde le fichier JAR par jar tf myjarfile, je peux voir le PropHolder.class répertorié ici.

Btw: le code fonctionne correctement sur ma machine locale. Mais cela ne fonctionnait pas lorsque je le déployais 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?

145
Leon

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 se soit propagée jusqu'au ClassLoader tentant de charger la classe. Nous aurions cependant besoin d’un stacktrace pour le confirmer.

Cela ou cela s'est produit lors de la création de la variable statique PropHolder.prop.

181
John Vint

Vous obtenez un Java.lang.NoClassDefFoundError qui 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 la classe lors de la tentative de lecture de la classe.

Mettez un try/catch à l'intérieur de votre initialiseur statique et regardez l'exception. Si vous lisez certains fichiers et qu’ils diffèrent de votre environnement local, c’est très probablement la cause du problème (le fichier est peut-être introuvable, aucune autorisation, etc.).

111
jeha

NoClassDefFoundError ne donne pas beaucoup d'indices sur ce qui ne va pas 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;
  }
}
30
Mark Hansen

J'ai eu la même exception, voici comment j'ai résolu le problème:

Préconditions:

  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 de l'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 parent nécessitait également certaines classes initialisées à partir du contexte de l'application.

J'espère que cela aidera.

3
KerenSi

Comme mentionné ci-dessus, cela pourrait être un certain nombre de choses. Dans mon cas, j'avais une variable initialisée de manière statique 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.

1
TriMix

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 cela ne suffisait pas. 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

1
Elad

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

Mon problème appelait Uri.parse(uriString) 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 ne l'a pas trouvée. J'ai changé cette valeur en null à la place et tout est rentré dans l'ordre.

0
lifeson106

Il y a quelques jours à peine, j'ai rencontré la même question, tout comme la vôtre. Tout le code fonctionne bien sur mon ordinateur local, mais génère une erreur (noclassdeffound & initialize). Donc, je publie ma solution, mais je ne sais pas pourquoi, je fais simplement avancer une possibilité. J'espère que quelqu'un le saura l'expliquer. @ John Vint Tout d'abord, je vais vous montrer mon problème. Mon code a la variable statique et le bloc statique les deux. Lorsque j'ai rencontré ce problème pour la première fois, j'ai essayé la solution de John Vint et essayé de détecter l'exception. Cependant, je n'ai rien attrapé. Alors j'ai pensé que c'était parce que la variable statique (mais maintenant je sais que c'est la même chose) et je n'ai toujours rien trouvé. Donc, j'essaie 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 au cours d’un même processus (d’ailleurs, la machine Linux a un double cœur et un double processus). 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, tout va mal, mais si elles s'exécutent dans des processus différents, les deux sont correctes. Dans la machine Linux, j'utilise

mvn -U clean  test -Dtest=path 

pour exécuter une tâche, et comme ma variable statique est de démarrer un conteneur (ou peut-être d'initialiser un nouveau chargeur de classes), il restera en place jusqu'à l'arrêt de JVM, et 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 cela rendra le jvm confus. En conséquence, l'erreur se produit. Alors, comment le résoudre? Ma solution consiste à ajouter une nouvelle commande à la commande maven et à 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érez toujours que cela aidera d’autres personnes qui rencontrent le même problème.

0
MonkeyKing