Pourquoi NoClassDefFoundError causée par un champ statique de l'initialisation de l'échec?
Voici un intéressant java question.
suivantes simple programme java contient un champ statique initialisé par une méthode statique. En fait, j'ai de la force de la méthode de calculer la intiailize valeur pour élever un NullPointException, Quand je accéder à un champ statique, un NoClassDefFoundError seront soulevées. il semble que la VM traiter la Classe n'est pas complète.
Mais lorsque j'accède à la Classe, il toujours disponible;
Personne ne sait pourquoi?
class TestClass {
public static TestClass instance = init();
public static TestClass init() {
String a = null;
a.charAt(0); //force a null point exception;
return new TestClass();
}
}
class MainClass {
static public void main(String[] args) {
accessStatic(); //a ExceptionInInitializerError raised cause by NullPointer
accessStatic(); //now a NoClassDefFoundError occurs;
//But the class of TestClass is still available; why?
System.out.println("TestClass.class=" + TestClass.class);
}
static void accessStatic() {
TestClass a;
try {
a = TestClass.instance;
} catch(Throwable e) {
e.printStackTrace();
}
}
}
- C'est surprenant pour moi, trop! Je ping un ami qui pourrait connaître la réponse; nous allons voir s'il répond.
- Je pense que, le chargeur de classe ne parvient pas à charger la
TestClass
en raison de l'exception dans l'initialiseur statique - cette partie est triviale; je ne crois pas qu'il demande même à ce sujet. Ce qui est étonnant, est le troisième impression qui montre que
TestClass.class
dansMainClass
contient en fait une référence à un objet physiqueClass
objet. Si la classe n'est pas correctement initialisé, pourquoi sommes-nous autorisés à toucher à tous? TestClass.class
ne semble pas déclencher de chargement de classe et on dirait qu'il est accessible et disponible indifférent de savoir si ou non la classe a été chargé.
Vous devez vous connecter pour publier un commentaire.
La réponse à ces questions est généralement enterré quelque part dans les specs... (§12.4.2)
Ce qui se passe lorsque les classes sont initialisés:
Les étapes 1 à 4 sont un peu étrangers à cette question. Étape 5 ici est ce qui déclenche l'exception:
6-8 poursuivre l'initialisation, 8 exécute les initialiseurs, et ce qu'il se passe est à l'étape 9:
Mais nous avons eu une erreur dans l'initialiseur, donc:
Yep, nous voyons un
ExceptionInInitializerError
b/c de l'exception de pointeur null.Et puis la classe est marquée erronée qui est pourquoi nous sommes l'exception de l'étape 5 de la deuxième fois.
Probablement parce que
TestClass
existe toujours, c'est juste marqué erronée. Il a déjà été chargée et vérifiées.Oui, c'est généralement pourquoi
NoClassDefFoundError
est soulevée. C'est mal nommé, c'est tout. Il aurait été nommé en tant que "classe init exception d'échec" ou de quelque chose.Parce que le nom trompeur, les programmeurs java qui est eu cette erreur gaspillé des centaines de homme des années à essayer de comprendre pourquoi la classe ne peut pas être trouvé.
Chaque fois que vous voyez cette exception, vous devriez vérifier le journal d'en haut, et essayer de trouver la cause racine lorsque la classe a échoué à init.
NoClassDefFoundError
la première fois qu'il a été soulevé.NoClassDefFoundError
a certainement son utilisation dans d'autres circonstances (par exemple, la définition de la classe n'est pas trouvé lors de l'exécution de chemin de classe alors qu'il était sûr qu'il était disponible dans le compile-time classpath).NoClassDefFoundError
est qu'il ne prend pas uncause
. Cela a entraîné des millions, voire des milliards de dollars en perte de productivité. Un incroyablement idiot décision.Que c'est correct ...
Oui.
Le chargeur de classe n'a pas essayé de supprimer le cassé de la classe parce que:
À entrer dans un état où cette incohérence est visible, votre application a pour attraper
ClassDefNotFoundError
(ou une super-classe) et a tenté de la récupérer. Il est un fait bien documenté queError
les exceptions sont généralement pas récupérables; c'est à dire si vous tentez de récupérer, la JVM peut se retrouver dans un état incohérent. C'est ce qui s'est passé ici ... à l'égard des classes qui ont été en cours de chargement /initialisé.il est limité
8.3.2.2 de http://psc.informatik.uni-jena.de/languages/Java/javaspec-3.pdf