2017-02-01 2 views
0

J'ai la méthode ci-dessous dans la classe A. Toutes les classes A, B, C et la classe principale à partir de laquelle «A» est invoqué sont dans le même pot.Comment résoudre java.lang.NoClassDefFoundError se produisant dans le même pot?

public class A {  
    private static void init() { 
     if (!init) { 
      synchronized (B.class) { 
       if (!init) { 
        map = C.creat(); 
        init = true; 
       } 
      } 
     } 
    } 
} 

Le code est de lancer un Throwable, java.lang.NoClassDefFoundError au bloc synchronized (ligne n ° 4). Quelle peut être la raison pour laquelle toutes les classes sont dans le même jar, il n'y a aucune chance de ne pas trouver une classe pendant l'exécution.

J'ai parcouru la solution en Existing Question mais je n'ai pas trouvé de solution. S'il vous plaît aider.

Il y a des blocs d'initialisation statiques et variables statiques dans la classe B.

Le problème peut être résolu, si j'utilise un static object/class A pour synchroniser le morceau de code au lieu de « B ». Je suis curieux de savoir pourquoi j'ai fait face à l'exception et comment la réparer en utilisant la classe B seulement.

+2

Pourquoi utilisez-vous B.class pour synchroniser? Je ne pense pas que ce soit une bonne pratique. – duffymo

+0

Se pourrait-il que les blocs statiques dans B appellent la méthode 'A.init'? – RealSkeptic

+0

Pouvez-vous montrer la structure du paquet du pot?Vous pouvez vous décompiler jd-gui – Optimus

Répondre

0

Si vous avez vraiment compilé ce code dans un fichier JAR; et que JAR contient B.class; alors cela ne peut pas arriver.

Les seules options sont: le fichier JAR que vous utilisez est corrompu; ou il ne contient pas ce que vous supposez qu'il devrait contenir.

Ainsi: vérifiez votre JAR. Quelque chose doit être faux à ce sujet. Par exemple, utilisez jar tf jarfile.jar pour lister le contenu complet; et vérifiez si B.class est réellement actif.

0

Les objets de classe ou les métadonnées sont chargés par les chargeurs de classe tout en permettant le lancement de l'application Java.

Le code ci-dessus peut se retrouver dans java.lang.NoClassDefFoundError en raison de ce qui suit. La méthode statique ci-dessus init est invoquée depuis un bloc statique dans la classe A. Il peut arriver que la classe B ne soit toujours pas chargée avant la classe A et que le chargeur de classe tente de verrouiller l'objet classe (métadonnées) de classe B et ne parvient pas à trouver la définition de la classe.

Il fonctionne si vous syncronise sur A.class parce que le classloader a la classe méta référence de celui-ci

Afin de rendre le travail avec la classe B.class vous devrez peut-être invoquer paresseusement la méthode d'initialisation en classe A et autoriser le chargeur de classe à charger les méta-informations des classes. Evitez d'invoquer la méthode init() dans la classe A à partir de tout bloc d'initialisation statique.

+0

Pas exactement correct. La référence à 'B.class' déclenchera le chargement de' B'. C'est dans la JLS. Comme le fait que la référence à 'B.class' ne déclenchera pas l'initialisation de la classe. –

0

Avez-vous fait référence à une méthode ou à une variable dans B avant l'utilisation de B.class? Si non, alors B n'a pas, encore une fois, été initialisé. La référence au littéral class ne déclenche pas l'initialisation de la classe. "Bloc statique" est un terme incorrect. C'est "statique initialiseur bloc". Ce qui n'a pas été exécuté.

Utilisez un final Object membre de A ou B pour synchroniser, pas le littéral class.