Java ClassLoader
Java ClassLoader ist eine abstrakte Klasse. Es gehört zu einem java.lang Paket. Es lädt Klassen aus verschiedenen Ressourcen. Java ClassLoader wird verwendet, um die Klassen zur Laufzeit zu laden. Mit anderen Worten: JVM führt den Verknüpfungsprozess zur Laufzeit durch. Klassen werden je nach Bedarf in die JVM geladen. Wenn eine geladene Klasse von einer anderen Klasse abhängt, wird diese Klasse ebenfalls geladen. Wenn wir das Laden einer Klasse anfordern, delegiert sie die Klasse an ihre übergeordnete Klasse. Auf diese Weise bleibt die Einzigartigkeit in der Laufzeitumgebung erhalten. Es ist unbedingt erforderlich, ein Java-Programm auszuführen.
sed-Befehl
Java ClassLoader basiert auf drei Prinzipien: Delegation , Sichtweite , Und Einzigartigkeit .
Arten von ClassLoader
In Java verfügt jeder ClassLoader über einen vordefinierten Speicherort, von dem aus er Klassendateien lädt. Es gibt folgende Arten von ClassLoader in Java:
Bootstrap-Klassenlader: Es lädt Standard-JDK-Klassendateien aus rt.jar und anderen Kernklassen. Es ist ein übergeordnetes Element aller Klassenlader. Es hat kein übergeordnetes Element. Wenn wir String.class.getClassLoader() aufrufen, gibt es null zurück und jeder darauf basierende Code löst eine NullPointerException aus. Es wird auch Primordial ClassLoader genannt. Es lädt Klassendateien aus jre/lib/rt.jar. Zum Beispiel die Paketklasse java.lang.
Klassenlader für Erweiterungen: Es delegiert die Anforderung zum Laden der Klasse an sein übergeordnetes Element. Wenn das Laden einer Klasse nicht erfolgreich ist, werden Klassen aus dem Verzeichnis jre/lib/ext oder einem anderen Verzeichnis als java.ext.dirs geladen. Es wird von sun.misc.Launcher$ExtClassLoader in JVM implementiert.
Systemklassenlader: Es lädt anwendungsspezifische Klassen aus der Umgebungsvariablen CLASSPATH. Es kann beim Aufrufen des Programms mit den Befehlszeilenoptionen -cp oder classpath festgelegt werden. Es ist ein untergeordnetes Element der Erweiterung ClassLoader. Es wird durch die Klasse sun.misc.Launcher$AppClassLoader implementiert. Alle Java ClassLoader implementieren java.lang.ClassLoader.
Wie ClassLoader in Java funktioniert
Wenn die JVM eine Klasse anfordert, ruft sie eine Methode „loadClass()“ der Klasse „java.lang.ClassLoader“ auf, indem sie den vollständig klassifizierten Namen der Klasse übergibt. Die Methode „loadClass()“ ruft die Methode „findLoadedClass()“ auf, um zu überprüfen, ob die Klasse bereits geladen wurde oder nicht. Es ist erforderlich, ein mehrfaches Laden der Klasse zu vermeiden.
Wenn die Klasse bereits geladen ist, wird die Anforderung zum Laden der Klasse an den übergeordneten ClassLoader delegiert. Wenn der ClassLoader die Klasse nicht findet, ruft er die Methode findClass() auf, um im Dateisystem nach den Klassen zu suchen. Das folgende Diagramm zeigt, wie ClassLoader mithilfe der Delegation Klassen in Java lädt.
Angenommen, wir haben eine anwendungsspezifische Klasse Demo.class. Die Anforderung zum Laden dieser Klassendateien wird an Application ClassLoader übertragen. Es delegiert an die übergeordnete Erweiterung ClassLoader. Darüber hinaus wird an Bootstrap ClassLoader delegiert. Bootstrap durchsucht diese Klasse in rt.jar und da diese Klasse nicht vorhanden ist. Fordern Sie nun die Übertragung an Extension ClassLoader an, der nach dem Verzeichnis jre/lib/ext sucht und versucht, diese Klasse dort zu finden. Wenn die Klasse dort gefunden wird, lädt Extension ClassLoader diese Klasse. Application ClassLoader lädt diese Klasse nie. Wenn die Erweiterung ClassLoader sie nicht lädt, lädt Application ClaasLoader sie aus CLASSPATH in Java.
Das Sichtbarkeitsprinzip besagt, dass der untergeordnete ClassLoader die vom übergeordneten ClassLoader geladene Klasse sehen kann, aber umgekehrt gilt das nicht. Das bedeutet, dass, wenn Application ClassLoader Demo.class lädt, in diesem Fall der Versuch, Demo.class explizit mit Extension ClassLoader zu laden, eine java.lang.ClassNotFoundException auslöst.
Gemäß dem Eindeutigkeitsprinzip sollte eine vom übergeordneten Element geladene Klasse nicht erneut vom untergeordneten ClassLoader geladen werden. Es ist also möglich, einen Klassenlader zu schreiben, der die Delegations- und Eindeutigkeitsprinzipien verletzt und die Klasse selbst lädt.
Kurz gesagt folgt der Klassenlader der folgenden Regel:
- Es prüft, ob die Klasse bereits geladen ist.
- Wenn die Klasse nicht geladen ist, bitten Sie den übergeordneten Klassenlader, die Klasse zu laden.
- Wenn der übergeordnete Klassenlader die Klasse nicht laden kann, versuchen Sie, sie in diesem Klassenlader zu laden.
Betrachten Sie das folgende Beispiel:
public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } }
Kompilieren Sie den obigen Code und führen Sie ihn mit dem folgenden Befehl aus:
javac Demo.java java -verbose:class Demo
-verbose:class: Es wird verwendet, um Informationen zu Klassen anzuzeigen, die von JVM geladen werden. Dies ist nützlich, wenn Sie den Klassenlader zum dynamischen Laden von Klassen verwenden. Die folgende Abbildung zeigt die Ausgabe.
Wir können beobachten, dass die von der Anwendungsklasse (Demo) benötigten Laufzeitklassen zuerst geladen werden.
Wenn Klassen geladen werden
Es gibt nur zwei Fälle:
- Wenn der neue Bytecode ausgeführt wird.
- Wenn der Bytecode einen statischen Verweis auf eine Klasse herstellt. Zum Beispiel, System.out .
Statisches vs. dynamisches Klassenladen
Klassen werden statisch mit dem Operator „new“ geladen. Das dynamische Laden von Klassen ruft die Funktionen eines Klassenladers zur Laufzeit mithilfe der Methode Class.forName() auf.
Unterschied zwischen loadClass() und Class.forName()
Die Methode „loadClass()“ lädt nur die Klasse, initialisiert jedoch nicht das Objekt. Während die Methode Class.forName() das Objekt nach dem Laden initialisiert. Wenn Sie beispielsweise ClassLoader.loadClass() zum Laden des JDBC-Treibers verwenden, lässt der Klassenlader das Laden des JDBC-Treibers nicht zu.
Die Methode java.lang.Class.forName() gibt das Klassenobjekt zurück, das mit der Klasse oder den Schnittstellen mit dem angegebenen Zeichenfolgennamen verknüpft ist. Es löst eine ClassNotFoundException aus, wenn die Klasse nicht gefunden wird.
Beispiel
In diesem Beispiel wird die Klasse java.lang.String geladen. Es gibt den Klassennamen, den Paketnamen und die Namen aller verfügbaren Methoden der String-Klasse aus. Im folgenden Beispiel verwenden wir Class.forName().
Klasse: Stellt ein Klassenobjekt dar, das einen beliebigen Typ haben kann (? ist ein Platzhalter). Der Klassentyp enthält Metainformationen über eine Klasse. Der Typ von String.class ist beispielsweise Class. Verwenden Sie Class, wenn die modellierte Klasse unbekannt ist.
getDeclaredMethod(): Gibt ein Array zurück, das Methodenobjekte enthält, die alle deklarierten Methoden der Klasse oder Schnittstelle widerspiegeln, die durch dieses Klassenobjekt dargestellt wird, einschließlich öffentlicher, geschützter Methoden, Standardzugriffsmethoden (Paketzugriff) und privater Methoden, jedoch ohne geerbte Methoden.
getName(): Es gibt den durch dieses Methodenobjekt dargestellten Methodennamen als String zurück.
import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Ausgabe
Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0