---
title: Klassenlader
url: 'https://tutego.de/blog/javainsel/2018/09/klassenlader-verbose-class'
markdown: 'https://tutego.de/blog/javainsel/2018/09/klassenlader-verbose-class.md'
date: '2018-09-25'
description: 'Ein Klassenlader ist dafür verantwortlich, die Binärrepräsentation einer Klasse aus einem Hintergrundspeicher oder Hauptspeicher zu laden. Aus der Datenquelle (im Allgemeinen die .class-Datei) liefert der Klassenlader ein Byte-Array mit den Informationen, die im zweiten Schritt dazu verwendet werde…'
taxonomy:
  category:
    - Insel
---

# Klassenlader

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://tutego.de/blog/javainsel/)

## Klassenlader

25.09.2018 · [Christian Ullenboom](https://tutego.de/blog/javainsel/author/admin/)

Ein Klassenlader ist dafür verantwortlich, die Binärrepräsentation einer Klasse aus einem Hintergrundspeicher oder Hauptspeicher zu laden. Aus der Datenquelle (im Allgemeinen die .class-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öglichkeit, eigene Klassenlader zu schreiben, um etwa verschlüsselte vom Netzwerk zu beziehen oder komprimierte .class-Dateien aus Datenbanken zu laden.

### Klassenladen auf Abruf

Nehmen wir zu Beginn ein einfaches Programm mit drei Klassen:

```java
package com.tutego.insel.tool;

public class HambachForest {

public static void main( String[] args ) {

boolean rweWantsToCutTrees = true;

Forrest hambachForest = new Forrest();

if ( rweWantsToCutTrees ) {

Protest<Forrest> p1 = new Protest<>();

p1.believeIn = hambachForest;

}

}

}

class Forrest { }

class Protest<T> {

T believeIn;

java.time.LocalDate since;

}
```

Wenn die Laufzeitumgebung das Programm `HambachForest` startet, muss sie eine Reihe von Klassen laden. Das tut sie dynamisch zur Laufzeit. Sofort wird klar, dass es zumindest `HambachForest` sein muss. Und da die JVM die statische main(`String`\[\])-Methode aufruft und Optionen übergibt, muss auch `String` geladen sein. Unsichtbar stecken noch andere referenzierte Klassen dahinter, die nicht direkt sichtbar sind. So wird zum Beispiel `Object` geladen, da implizit in der Klassendeklaration von `HambachForest` steht: class `HambachForest` extends `Object`. Intern ziehen die Typen viele weitere Typen nach sich. `String` implementiert Serializable, CharSequence und `Comparable`, also müssen diese drei Schnittstellen auch geladen werden. Und so geht das weiter, je nachdem, welche Programmpfade abgelaufen werden. Wichtig ist aber, zu verstehen, dass diese Klassendateien so spät wie möglich geladen werden.

### Klassenlader bei der Arbeit zusehen

Im Beispiel lädt die Laufzeitumgebung selbstständig die Klassen (implizites Klassenladen). Klassen lassen sich auch mit `Class.forName(String)` über ihren Namen laden (explizites Klassenladen).

Um zu sehen, welche Klassen überhaupt geladen werden, lässt sich der virtuellen Maschine beim Start der Laufzeitumgebung ein Schalter mitgeben: -verbose:class. Dann gibt die Maschine beim Lauf alle Typen aus, die sie lädt. Nehmen wir das Beispiel von eben, so ist die Ausgabe mit dem aktivierten Schalter unter Java 11 fast 500 Zeilen lang; ein Ausschnitt:

$ **java -verbose:class `com.tutego.insel.tool.HambachForest`**

\[0.010s\]\[info\]\[class,load\] opened: C:\\Program `Files`\\Java\\jdk-11\\lib\\modules

\[0.032s\]\[info\]\[class,load\] `java.lang.Object` source: jrt:/java.base

\[0.032s\]\[info\]\[class,load\] `java.io.Serializable` source: jrt:/java.base

\[0.033s\]\[info\]\[class,load\] `java.lang.Comparable` source: jrt:/java.base

\[0.036s\]\[info\]\[class,load\] `java.lang.CharSequence` source: jrt:/java.base

\[0.037s\]\[info\]\[class,load\] `java.lang.String` source: jrt:/java.base

…

\[0.684s\]\[info\]\[class,load\] sun.security.util.Debug source: jrt:/java.base

\[0.685s\]\[info\]\[class,load\] `com.tutego.insel.tool`.**`HambachForest`** source: file:/C:/Inselprogramme/target/classes/

\[0.687s\]\[info\]\[class,load\] `java.lang.PublicMethods$MethodList` source: jrt:/java.base

\[0.687s\]\[info\]\[class,load\] `java.lang.PublicMethods$Key` source: jrt:/java.base

\[0.689s\]\[info\]\[class,load\] `java.lang.Void` source: jrt:/java.base

\[0.690s\]\[info\]\[class,load\] `com.tutego.insel.tool`.**`Forrest`** source: file:/C:/Inselprogramme/target/classes/

\[0.691s\]\[info\]\[class,load\] jdk.internal.misc.TerminatingThreadLocal$1 source: jrt:/java.base

\[0.692s\]\[info\]\[class,load\] `java.lang.Shutdown` source: jrt:/java.base

\[0.692s\]\[info\]\[class,load\] `java.lang.Shutdown$Lock` source: jrt:/java.base

Ändern wir die Variable `rweWantsToCutTrees` auf `true`, so wird unsere Klasse `Protest` geladen, und in der Ausgabe kommt nur eine Zeile hinzu! Das wundert auf den ersten Blick, denn die Klasse referenziert `LocalDate`. Doch ein `LocalDate` wird nicht benötigt, also auch nicht geladen. Der Klassenlader bezieht nur Klassen, wenn die für den Programmablauf benötigt werden, nicht aber durch die reine Deklaration als Attribut. Wenn wir `LocalDate` mit zum Beispiel `LocalDate.now()` initialisieren kommen stattliche 200 Klassendateien hinzu.

Kategorien: [Insel](https://tutego.de/blog/javainsel/category/insel/)

[← Alle Beiträge](https://tutego.de/blog/javainsel/)

---

## Navigation

- Previous: [Eclipse 4.9 (2018-09) ist fertig, Spring Tool Suite 3.9.6 setzt sofort drauf auf](https://tutego.de/blog/javainsel/2018/09/eclipse-4-9-2018-09-ist-fertig-spring-tool-suite-3-9-6-setzt-sofort-drauf-auf.md)
- Next: [Java 11 ist draußen](https://tutego.de/blog/javainsel/2018/09/java-11-ist-draussen.md)
