{"id":3261,"date":"2015-12-19T14:23:58","date_gmt":"2015-12-19T12:23:58","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=3261"},"modified":"2015-12-19T14:23:58","modified_gmt":"2015-12-19T12:23:58","slug":"klassenlader-class-loader-klassenpfad","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2015\/12\/klassenlader-class-loader-klassenpfad\/","title":{"rendered":"Klassenlader (Class Loader) und Klassenpfad"},"content":{"rendered":"<p>Ein Klassenlader ist daf\u00fcr verantwortlich, eine Klasse zu laden. Aus der Datenquelle (im Allgemeinen einer Datei) liefert der Klassenlader ein Byte-Array mit den Informationen, die im zweiten Schritt dazu verwendet werden, die Klasse ins Laufzeitsystem einzubringen; das ist Linking. Es gibt vordefinierte Klassenlader und die M\u00f6glichkeit, eigene Klassenlader zu schreiben, um etwa verschl\u00fcsselte und komprimierte .class-Dateien aus Datenbanken zu laden.<\/p>\n<h3>Klassenladen auf Abruf<\/h3>\n<p>Nehmen wir zu Beginn ein einfaches Programm mit zwei Klassen:<\/p>\n<pre>class\u00a0Person\u00a0{\r\n \u00a0 static String NOW = java.time.LocalDateTime.now().toString();<\/pre>\n<pre>\r\n \u00a0\u00a0public\u00a0static\u00a0void\u00a0main(\u00a0String[]\u00a0args\u00a0)\u00a0{\r\n \u00a0\u00a0\u00a0\u00a0Dog\u00a0wuffi\u00a0=\u00a0new\u00a0Dog();\r\n \u00a0\u00a0}\r\n }\r\n \r\n class\u00a0Dog\u00a0{\r\n \u00a0\u00a0Person\u00a0master;\r\n }<\/pre>\n<p>Wenn die Laufzeitumgebung das Programm Person startet, muss sie eine Reihe von Klassen laden. Das tut sie dynamisch zur Laufzeit. Sofort wird klar, dass es zumindest Person sein muss. Wenn aber die statische main(String[])-Methode aufgerufen wird, muss auch Dog geladen sein. Und da beim Laden einer Klasse auch die statischen Variablen initialisiert werden, wird auch die Klasse LocalDateTime geladen.<\/p>\n<p>Zwei weitere Dinge werden nach einiger \u00dcberlegung deutlich:<\/p>\n<ul>\n<li>Wenn Dog geladen wird, bezieht es sich auf Person. Da Person aber schon geladen ist, muss es nicht noch einmal geladen werden.<\/li>\n<li>Unsichtbar stecken noch andere referenzierte Klassen dahinter, die nicht direkt sichtbar sind. So wird zum Beispiel Object geladen, da implizit in der Klassendeklaration von Person steht: class Person extends Object. Auch String muss geladen werden, weil String einmal in der Signatur von main(String[]) vorkommt und es der Typ von now Intern ziehen die Typen viele weitere Typen nach sich. String implementiert Serializable, CharSequence und Comparable, also m\u00fcssen diese drei Schnittstellen auch geladen werden. Und so geht das weiter, je nach dem, welche Programmpfade abgelaufen werden. Wichtig ist aber zu verstehen, dass diese Klassendateien so sp\u00e4t wie m\u00f6glich geladen werden.<\/li>\n<\/ul>\n<p>Im Beispiel mit den Klassen Person und Dog l\u00e4dt die Laufzeitumgebung selbstst\u00e4ndig die Klassen (implizites Klassenladen). Klassen lassen sich auch mit Class.forName(String) \u00fcber ihren Namen laden (explizites Klassenladen).<\/p>\n<p><strong>Hinweis<\/strong>.\u00a0Um zu sehen, welche Klassen \u00fcberhaupt geladen werden, l\u00e4sst sich der virtuellen Maschine beim Start der Laufzeitumgebung ein Schalter mitgeben -verbose:class. Dann gibt die Maschine beim Lauf alle Klassen aus, die sie l\u00e4dt.<\/p>\n<h3>JAR-Dateien<\/h3>\n<p>Gro\u00dfe Sammlungen von Java-Klassendatein und Ressourcen werden in sogenannten Java-Archiven, kurz JAR-Dateien, zusammengefasst. Diese Dateien sind im Grunde ganz normale ZIP-Archive mit einem besonderen Verzeichnis META-INF f\u00fcr Meta-Dateien. Das JDK bringt im bin-Verzeichnis das Werkzeug jar zum Aufbau und Extrahieren von JAR-Dateien mit.<\/p>\n<p>JAR-Dateien behandelt die Laufzeitumgebung wie Verzeichnisse von Klassendateien und Ressourcen. Wenn Java-Software ausgeliefert wird, dann bieten sich JAR-Dateien an, denn es ist einfacher, nur ein komprimiertes Archiv weiterzugehen als einen gro\u00dfen Dateibaum. Zudem haben Java-Archive den Vorteil, dass sie signiert werden k\u00f6nnen und illegale \u00c4nderungen auffallen.<\/p>\n<h3>Woher die kleinen Klassen kommen: Die Suchorte und spezielle Klassenlader<\/h3>\n<p>Die Laufzeitumgebung nutzt zum Laden nicht nur einen Klassenlader, sondern mehrere. Die Java-Laufzeitumgebung nutzt diese verschiedenen Klassenlader um unterschiedliche Orte festzulegen. Ein festes Schema bestimmt die Suche nach den Klassen:<\/p>\n<ol>\n<li>Klassen Typen wie String, Object oder Point stehen in einem ganz speziellen Archiv. Wenn ein eigenes Java-Programm gestartet wird, so sucht die virtuelle Maschine die angeforderten Klassen zuerst in diesem Archiv. Da es elementare Klassen sind, die zum Hochfahren eines Systems geh\u00f6ren, werden sie Bootstrap-Klassen Das Archiv mit diesen Klassen hei\u00dft oft rt.jar (f\u00fcr Runtime). Andere Archive k\u00f6nnen hinzukommen \u2013 wie i18n.jar, das Internationalisierungsdaten beinhaltet. Die Implementierung dieses Bootstrap-Klassenlader ist nicht \u00f6ffentlich und wird von System zu System unterschiedlich sein. Ab Java 9 wird sich das grundlegend \u00e4ndern.<\/li>\n<li>Ist eine Klasse keine Bootstrap-Klasse, beginnt der System-Klassenlader Applikations-Klassenlader die Suche im Klassenpfad (Classpath). Diese Pfadangabe besteht aus einer Aufz\u00e4hlung einzelner Klassendateien, Verzeichnisse, Klassen oder JAR-Archive, in denen die Laufzeitumgebung nach den Klassendateien sucht. Standardm\u00e4\u00dfig ist dieser Klassenpfad auf das aktuelle Verzeichnis gesetzt (\u201e.\u201c), er l\u00e4sst sich aber beliebig setzen.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Ein Klassenlader ist daf\u00fcr verantwortlich, eine Klasse zu laden. Aus der Datenquelle (im Allgemeinen einer Datei) liefert der Klassenlader ein Byte-Array mit den Informationen, die im zweiten Schritt dazu verwendet werden, die Klasse ins Laufzeitsystem einzubringen; das ist Linking. Es gibt vordefinierte Klassenlader und die M\u00f6glichkeit, eigene Klassenlader zu schreiben, um etwa verschl\u00fcsselte und komprimierte [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11],"tags":[],"class_list":["post-3261","post","type-post","status-publish","format-standard","hentry","category-insel"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/3261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=3261"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/3261\/revisions"}],"predecessor-version":[{"id":3262,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/3261\/revisions\/3262"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=3261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=3261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=3261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}