2017-02-01 3 views
0

Ich habe die folgende Methode in Klasse A. Alle Klassen A, B, C und die Hauptklasse, von der 'A' aufgerufen wird, befinden sich in demselben Glas.Wie löst man java.lang.NoClassDefFoundError im selben Jar?

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

Der Code wirft eine Throwable, java.lang.NoClassDefFoundError am synchronized Block (Linie No.4). Was kann der Grund sein, da alle Klassen im gleichen Jar sind, gibt es keine Möglichkeit während der Laufzeit keine Klasse zu finden.

Ich habe die Lösung in Existing Question durchgegangen, konnte aber keine Lösung finden. Bitte helfen Sie.

Es gibt statische Initialisierungsblöcke und statische Variablen in der Klasse B.

Das Problem behoben werden kann, wenn ich eine static object/class A verwenden Sie das Stück Code zu synchronisieren anstelle von ‚B‘. Ich bin neugierig zu wissen, warum ich die Ausnahme behandelt habe und wie man es nur mit Klasse B beheben kann.

+2

Warum verwenden Sie B.class zum Synchronisieren? Ich denke nicht, dass dies eine Best Practice ist. – duffymo

+0

Könnte es sein, dass die statischen Blöcke in B die 'A.init' Methode aufrufen? – RealSkeptic

+0

Können Sie die Paketstruktur des Glases zeigen?Du kannst jd-gui dekompilieren – Optimus

Antwort

0

Wenn Sie wirklich kompiliert , dass Code in ein JAR; und diese JAR enthält B.class; dann kann das nicht passieren.

Die einzigen Optionen sind: die JAR, die Sie verwenden, wurde beschädigt; oder es enthält nicht das, was Sie annehmen sollen.

Also: verifizieren Sie Ihre JAR. Da muss etwas falsch sein. Verwenden Sie beispielsweise jar tf jarfile.jar, um den vollständigen Inhalt aufzulisten; und überprüfen, ob B.class wirklich in ist.

0

Das Klassenobjekt oder die Metadaten werden von den Klassenladeprogrammen geladen, während das Starten der Java App erfolgt.

Der obige Code kann aufgrund der folgenden in java.lang.NoClassDefFoundError enden.

1> Die obige statische Methode init wird von einem statischen Block in Klasse A aufgerufen. Es kann passieren, dass die Klasse B noch nicht vor Klasse A geladen ist und der Klassenlader versucht, das Klassenobjekt (Metadaten) zu sperren. der Klasse B und findet die Definition der Klasse nicht.

Es funktioniert, wenn Sie auf A.class syncronise, weil die Klassenlader die Klasse Meta-Referenz hat

Um die Arbeit mit Klasse zu machen B.class Sie träge haben die init-Methode in der Klasse A aufzurufen und Erlaube dem Klassenlader, die Metainformationen der Klassen zu laden. Vermeiden Sie es, die init() - Methode in der Klasse A von einem statischen Initialisierungsblock aus aufzurufen.

+0

Nicht genau richtig. Der Verweis auf 'B.class' löst das Laden von' B' aus. Es ist in der JLS. Wie auch die Tatsache, dass der Verweis auf 'B.class' keine Klasseninitialisierung auslöst. –

0

Hatte irgendetwas Bezug auf eine Methode oder Variable in B vor der Verwendung von B.class? Wenn nicht, dann wurde B nicht wiederholt, nicht initialisiert. Die Referenz auf das class-Literal löst keine Klasseninitialisierung aus. "Statischer Block" ist ein falscher Ausdruck. Es ist "statisch Initialisierer Block". Was nicht gelaufen ist.

Verwenden Sie ein final Object Mitglied von entweder A oder B, um zu synchronisieren, nicht das class Literal.

Verwandte Themen