findLoadedClass () gibt null zurück

8

Laut der JVM-Spezifikation , der Klassenlader, der das Laden einer Klasse initiiert, wird von der JVM als initiierender Klassenlader registriert. Desweiteren, gemäß dem JavaDoc von ClassLoader # findLoadedClass () die Methode

  

Gibt die Klasse mit dem angegebenen Binärnamen zurück, wenn dieser Loader von der Java Virtual Machine als initiierender Loader einer Klasse mit diesem Binärnamen aufgezeichnet wurde.

(Betonung meiner)

Betrachten Sie einen einfachen Klassenlader

%Vor%

Da foo.Bar tatsächlich im Klassenpfad existiert, druckt new SimpleClassLoader().foo()

%Vor%

Laut den oben genannten Gründen sollte SimpleClassLoader der initiierende Klassenlader sein und findLoadedClass("foo.Bar") sollte nur die erfolgreich geladene Klasse zurückgeben.

Betrachten Sie nun diese zweite Version:

%Vor%

Dies macht SimpleClassLoader2 sowohl zum initiierenden als auch zum definierenden Klassenlader von foo.Bar . In der Tat druckt new SimpleClassLoader2().foo() das gewünschte

%Vor%

Entweder ist die Dokumentation falsch oder ich verstehe nicht, warum SimpleClassLoader nicht als initiierender Klassenlader von foo.Bar angesehen wird. Kann jemand bitte etwas Licht in das werfen?

    
musiKk 23.02.2014, 00:37
quelle

1 Antwort

3

Ich habe noch ein paar Tests gemacht und bin mir ziemlich sicher, dass die Spezifikation korrekt implementiert wurde. Mein Fehler war, dass das reflektive Laden einer Klasse dasselbe ist wie das Laden als Teil des Auflösungsschrittes. Es macht Sinn: Sowohl die Spezifikation als auch die JavaDoc erwähnen das "Aufnehmen" eines Klassenladers als den initiierenden Klassenlader. Wenn ich loadClass() selbst anrufe, kann die VM nicht wissen, welcher Klassenlader der initiierende Klassenlader sein soll, also wird der definierende Klassenlader auch zum initiierenden Klassenladeprogramm.

Dies kann demonstriert werden, indem die geladene Klasse das Laden einer anderen Klasse ( foo.Baz ) als Teil der Abhängigkeitsauflösung auslöst, aber ein anderes Klassenladeprogramm das tatsächliche Laden durchführt. *

* Ich bin mir ziemlich sicher, dass das Verhalten eines gültigen Klassenladeprogramms nicht korrekt ist. Ich mache es nur, um einen Punkt zu veranschaulichen.

Betrachten Sie die folgenden Klassen (sie sind alle im Paket foo ):

%Vor%

und

%Vor%

Mein benutzerdefinierter Klassenlader wurde jetzt leicht modifiziert:

%Vor%

Der Test ist einfach:

%Vor%

Ausgabe ist

%Vor%

Wie man sieht: SimpleClassLoader leitet das Laden von ein und definiert auch foo.Bar . Beim Erstellen der Instanz wird die Auflösung von foo.Baz ausgelöst. Diesmal ist die Definition der Klasse an die Systemklassenlader, so dass es zum definierenden Klassenlader wird. Die Ausgabe zeigt, dass SimpleClassLoader den Klassenlader für beide Klassen startet, aber nur die erste Klasse definiert.

    
musiKk 24.02.2014, 21:55
quelle

Tags und Links