Was ist ein Java ClassLoader?

174

Was ist in wenigen einfachen Sätzen ein Java ClassLoader, wann wird er verwendet und warum?

OK, ich habe einen Wiki-Artikel gelesen. ClassLoader lädt Klassen. OK. Wenn ich also JAR-Dateien einbinde und importiere, erledigt ein ClassLoader die Aufgabe.

Warum sollte ich mich mit diesem ClassLoader beschäftigen? Ich habe es nie benutzt und wusste nicht, dass es existiert.

Die Frage ist, warum die ClassLoader-Klasse existiert. Und wie setzen Sie es in der Praxis ein? (Es gibt Fälle, ich weiß.)

EugeneP
quelle
Sie erhalten bessere Ergebnisse, wenn Sie Ihre Frage eingrenzen, z. B. indem Sie auf einen bestimmten Teil zeigen, den Sie nicht verstehen, wie er sich auf eine andere Sprache bezieht, mit der Sie vertraut sind usw.
JRL
75
Dies ist eine völlig vernünftige Frage, wenn man sie aus der Perspektive von jemandem betrachtet, der nach ein paar einfachen Sätzen sucht, um das Konzept zu erklären
oxbow_lakes
Dieses Video könnte von Interesse sein: Erhalten Sie wirklich Klassenlader?
Asmaier

Antworten:

231

Entnommen aus diesem schönen Tutorial von Sun:

Motivation

Anwendungen, die in statisch kompilierten Programmiersprachen wie C und C ++ geschrieben sind, werden in native, maschinenspezifische Anweisungen kompiliert und als ausführbare Datei gespeichert. Das Kombinieren des Codes zu einem ausführbaren nativen Code wird als Verknüpfen bezeichnet - das Zusammenführen von separat kompiliertem Code mit gemeinsam genutztem Bibliothekscode, um eine ausführbare Anwendung zu erstellen. Dies unterscheidet sich in dynamisch kompilierten Programmiersprachen wie Java. In Java bleiben die vom Java-Compiler generierten .class-Dateien unverändert, bis sie in die Java Virtual Machine (JVM) geladen werden. Mit anderen Worten, der Verknüpfungsprozess wird von der JVM zur Laufzeit ausgeführt. Klassen werden nach Bedarf in die JVM geladen. Und wenn eine geladene Klasse von einer anderen Klasse abhängt, wird auch diese Klasse geladen.

Wenn eine Java-Anwendung gestartet wird, ist die erste Klasse, die ausgeführt wird (oder der Einstiegspunkt in die Anwendung), die mit der öffentlichen statischen Void-Methode main (). Diese Klasse enthält normalerweise Verweise auf andere Klassen, und alle Versuche, die referenzierten Klassen zu laden, werden vom Klassenladeprogramm ausgeführt.

Betrachten Sie die folgende einfache Klasse, um ein Gefühl für dieses rekursive Laden von Klassen sowie für die Idee des Ladens von Klassen im Allgemeinen zu bekommen:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

Wenn Sie diese Klasse mit der Befehlszeilenoption -verbose: class ausführen, damit gedruckt wird, welche Klassen geladen werden, erhalten Sie eine Ausgabe, die wie folgt aussieht. Beachten Sie, dass dies nur eine Teilausgabe ist, da die Liste zu lang ist, um hier angezeigt zu werden.

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

Wie Sie sehen, werden zuerst die für die Anwendungsklasse (HelloApp) erforderlichen Java-Laufzeitklassen geladen.

Klassenlader in der Java 2-Plattform

Die Programmiersprache Java wird ständig weiterentwickelt, um das Leben der Anwendungsentwickler jeden Tag zu vereinfachen. Dazu werden APIs bereitgestellt, die Ihr Leben vereinfachen, indem Sie sich auf die Geschäftslogik konzentrieren können, anstatt Details grundlegender Mechanismen zu implementieren. Dies wird durch die kürzlich erfolgte Änderung von J2SE 1.5 auf J2SE 5.0 deutlich, um die Reife der Java-Plattform widerzuspiegeln.

Ab JDK 1.2 ist ein in die JVM integrierter Bootstrap-Klassenladeprogramm für das Laden der Klassen der Java-Laufzeit verantwortlich. Dieser Klassenladeprogramm lädt nur Klassen, die im Boot-Klassenpfad gefunden werden. Da es sich um vertrauenswürdige Klassen handelt, wird der Validierungsprozess nicht wie bei nicht vertrauenswürdigen Klassen ausgeführt. Zusätzlich zum Bootstrap-Klassenladeprogramm verfügt die JVM über einen Erweiterungsklassenladeprogramm, das für das Laden von Klassen aus Standarderweiterungs-APIs verantwortlich ist, und ein Systemklassenladeprogramm, das Klassen aus einem allgemeinen Klassenpfad sowie aus Ihren Anwendungsklassen lädt.

Da es mehr als einen Klassenlader gibt, werden sie in einem Baum dargestellt, dessen Stamm der Bootstrap-Klassenlader ist. Jeder Klassenlader hat einen Verweis auf seinen übergeordneten Klassenlader. Wenn ein Klassenlader aufgefordert wird, eine Klasse zu laden, konsultiert er seinen übergeordneten Klassenlader, bevor er versucht, das Element selbst zu laden. Der Elternteil wiederum konsultiert seinen Elternteil und so weiter. Erst wenn alle Klassenlader der Vorfahren die Klasse nicht finden können, wird der aktuelle Klassenlader beteiligt. Mit anderen Worten wird ein Delegierungsmodell verwendet.

Die java.lang.ClassLoader-Klasse

Dies java.lang.ClassLoaderist eine abstrakte Klasse, die von Anwendungen in Unterklassen unterteilt werden kann, die die Art und Weise erweitern müssen, in der die JVM Klassen dynamisch lädt. Mit Konstruktoren in java.lang.ClassLoader(und seinen Unterklassen) können Sie ein übergeordnetes Element angeben, wenn Sie einen neuen Klassenlader instanziieren. Wenn Sie kein übergeordnetes Element explizit angeben, wird der Systemklassenlader der virtuellen Maschine als übergeordnetes Standardelement zugewiesen. Mit anderen Worten, die ClassLoader-Klasse verwendet ein Delegierungsmodell, um nach Klassen und Ressourcen zu suchen. Daher ist jeder Instanz von ClassLoader ein übergeordneter Klassenlader zugeordnet, sodass die Aufgabe bei der Anforderung, eine Klasse oder Ressourcen zu finden, an ihren übergeordneten Klassenlader delegiert wird, bevor versucht wird, die Klasse oder Ressource selbst zu finden. Die loadClass()Methode des ClassLoader führt die folgenden Aufgaben aus, um beim Laden einer Klasse aufgerufen zu werden:

Wenn eine Klasse bereits geladen wurde, gibt sie sie zurück. Andernfalls wird die Suche nach der neuen Klasse an den übergeordneten Klassenlader delegiert. Wenn der übergeordnete Klassenladeprogramm die Klasse nicht findet, loadClass()ruft er die Methode findClass()zum Suchen und Laden der Klasse auf. Die finalClass()Methode sucht im aktuellen Klassenladeprogramm nach der Klasse, wenn die Klasse vom übergeordneten Klassenladeprogramm nicht gefunden wurde.


Der Originalartikel enthält weitere Informationen, die Ihnen auch zeigen, wie Sie Ihre eigenen Netzwerkklassenlader implementieren, und die Ihre Frage nach dem Warum (und Wie) beantworten. Siehe auch die API-Dokumente .

JRL
quelle
47

Die meisten Java-Entwickler müssen niemals explizit Klassenladeprogramme verwenden (außer um Ressourcen zu laden, damit es immer noch funktioniert, wenn sie in JARs gebündelt sind), geschweige denn, um ihre eigenen zu schreiben.

ClassLoaders werden in großen Systemen und Serveranwendungen verwendet, um Folgendes zu tun:

  • Modularisieren Sie ein System und laden, entladen und aktualisieren Sie Module zur Laufzeit
  • Verwenden Sie parallel verschiedene Versionen einer API-Bibliothek (z. B. einen XML-Parser)
  • Isolieren Sie verschiedene Anwendungen, die in derselben JVM ausgeführt werden (stellen Sie sicher, dass sie sich nicht gegenseitig stören, z. B. durch statische Variablen).
Michael Borgwardt
quelle
29

Die Frage ist "Warum sollte man sich die Mühe machen, dass diese ClassLoader-Klasse existiert"?

Nun, meistens, damit Sie Dinge reparieren können, wenn sie schief gehen :-).

Es ist wahr, solange Sie nur eine Anwendung schreiben, sie in eine JAR kompilieren und möglicherweise ein paar zusätzliche Bibliotheks-JARs einschließen, müssen Sie nichts über Klassenlader wissen, es wird einfach funktionieren.

Trotzdem ist es hilfreich, etwas über Klassenlader und das Laden von Klassen zu wissen, um besser zu verstehen, was sich hinter den Kulissen abspielt. Beispielsweise werden "statische Initialisierer" ausgeführt, wenn eine Klasse geladen wird. Um zu verstehen, wann sie ausgeführt werden, müssen Sie wissen, wie der Klassenlader entscheidet, wann sie geladen werden sollen.

auch .. wie benutzt man es in der Praxis?

Für einfache Fälle brauchen Sie sie nicht. Wenn Sie jedoch Code zur Laufzeit dynamisch mit expliziter Kontrolle darüber laden müssen, woher er stammt (z. B. Laden über ein Netzwerk, Laden von Plugins, die zur Kompilierungszeit nicht verfügbar sind usw.), müssen Sie möglicherweise mehr tun. Dann können Sie zB Ihren eigenen Klassenlader schreiben. Siehe die anderen Antworten für Links.

sleske
quelle
14

ClassLoaderin Java ist eine Klasse, die zum Laden von Klassendateien in Java verwendet wird. Java-Code wird vom javacCompiler in eine Klassendatei kompiliert, und JVM führt das Java-Programm aus, indem in die Klassendatei geschriebene Bytecodes ausgeführt werden.

ClassLoader ist für das Laden von Klassendateien aus dem Dateisystem, dem Netzwerk oder einer anderen Quelle verantwortlich. In Java, Bootstrap , Extension und System- oder Anwendungsklassenlader werden drei Standardklassenlader verwendet .

ClassLoader


Wie ClassLoader funktioniert

## ClassLoader-Interaktion mit JVM Geben Sie hier die Bildbeschreibung ein

Mehr @: how-classloader-works-in-java.html

Roottraveller
quelle
6

Klassenlader sind eine Funktionskomponente von JVM, die Klassendaten aus der '.class'-Datei oder über das Netzwerk in den Methodenbereich in Heap lädt.

Sieht aus wie ein integraler Bestandteil der JVM, aber warum sollte ich als Java-Endbenutzer besorgt sein? Hier ist warum:

Jeder Klassenlader hat seinen eigenen Namensraum und Klassen, die von einem bestimmten Klassenlader aufgerufen werden, gelangen in seinen Namensraum.

Klassen, die von zwei verschiedenen Klassenladeprogrammen aufgerufen werden, sind nicht übereinander sichtbar, was zu einer erhöhten Sicherheit führt.

Der übergeordnete untergeordnete Delegierungsmechanismus des Klassenladeprogramms stellt sicher, dass Java-API-Klassen niemals von nicht autorisiertem Code gehackt werden können.

Details finden Sie hier

Bitan
quelle
1

Klassenlader sind hierarchisch. Klassen werden in die JVM eingeführt, da sie in einer Klasse, die bereits in der JVM ausgeführt wird, namentlich referenziert werden.

Wie wurde die allererste Klasse geladen?
Die allererste Klasse wird mit Hilfe der static main()in Ihrer Klasse deklarierten Methode geladen . Alle anschließend geladenen Klassen werden von den Klassen geladen, die bereits geladen sind und ausgeführt werden.

Ein Klassenladeprogramm erstellt einen Namespace. Alle JVM enthalten mindestens einen Klassenlader, der in die JVM eingebettet ist und als primordialer (oder Bootstrap-) Klassenlader bezeichnet wird. Das ist eine Sache, und wir werden uns nicht-ursprüngliche Klassenlader ansehen. Die JVM verfügt über Hooks, mit denen benutzerdefinierte Klassenlader anstelle des ursprünglichen Klassenladers verwendet werden können. Hier sind die von der JVM erstellten Klassenlader.

Bootstrap (primordial) Dieser Klassenlader kann nicht wieder geladen werden. Lädt JDK-interne Klassen, Java. * -Pakete (lädt normalerweise rt.jar und i18n.jar). Erweiterungen Dieser Klassenlader kann nicht wieder geladen werden. Lädt JAR-Dateien aus dem JDK-Erweiterungsverzeichnis (normalerweise lib / ext von JRE). System Dieser Klassenlader kann nicht wieder geladen werden. Lädt Klassen aus dem Systemklassenpfad.

http://www.sbalasani.com/2015/01/java-class-loaders.html

Srinivas Balasani
quelle
1

Wenn Sie fragen, warum die ClassLoader-Klasse vorhanden ist, ist der Grund ziemlich einfach: Es ist die Klasse, die zum Suchen und Laden von Klassendateien zur Laufzeit verantwortlich ist .

Lassen Sie es uns näher erläutern.

In JVM wird jede Klasse von einer Instanz von geladen java.lang.ClassLoader. Immer wenn eine neue JVM von Ihrem üblichen Java-Programmstartbefehl gestartet wird java <classname>, besteht der erste Schritt darin, alle Schlüsselklassen in den Speicher zu laden, die für ein ordnungsgemäßes Funktionieren wie java.lang.Objectandere Laufzeitklassen erforderlich sind ( rt.jar).

ClassLoader besteht nun aus drei Teilen:

  • Der BootstrapClassLoaderist dafür verantwortlich, diese Klassen verfügbar zu machen, dh diese Klassen in den Speicher zu laden.

  • Die nächste Aufgabe besteht darin, externe Bibliotheken / JARs in den Speicher zu laden, damit die Anwendung ordnungsgemäß funktioniert. Der ExtClassLoaderist für diese Aufgabe verantwortlich. Dieser Klassenladeprogramm ist für das Laden aller im Pfad java.ext.dirs genannten .jar-Dateien verantwortlich.

  • Der dritte und wichtigste Klassenlader ist der AppClassLoader. Der Application Class Loader ist für das Laden der in der Systemeigenschaft java.class.path genannten Klassendateien verantwortlich.

Es ist auch wichtig zu beachten, dass die Standard-ClassLoader-Implementierungen überschrieben werden können, sodass Sie die JVM auf nützliche und interessante Weise anpassen und die Art und Weise, wie Klassendateien in das System gebracht werden, vollständig neu definieren können.

Geben Sie hier die Bildbeschreibung ein

Erfahren Sie mehr über Java Class Loader .

Johnny
quelle