ProgrammierungSenior Java Backend Entwickler

Wie funktioniert der Klassenlade-Mechanismus (class loading) in Java, welche Arten von Klassenlader gibt es und welche Probleme können bei ihrer falschen Verwendung auftreten?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

In Java werden Klassen von speziellen Objekten, den Klassenladern (class loaders), in den Speicher geladen. Jeder Klassenlader bildet seinen eigenen Namensraum für Klassen.

Arten von Klassenladern:

  1. Bootstrap ClassLoader — lädt grundlegende JDK-Klassen (rt.jar usw.).
  2. Extension ClassLoader — lädt Erweiterungen aus $JAVA_HOME/lib/ext.
  3. System (Application) ClassLoader — lädt Klassen aus dem classpath der Anwendung.
  4. Custom ClassLoader — benutzerdefinierte Lader für dynamisches Laden.

Besonderheiten:

  • Eine Klasse gilt als einzigartig im Rahmen der Kombination (class loader, Klassenname).
  • Zwei identische Klassen, die von verschiedenen Ladern geladen werden, gelten als unterschiedlich.
  • Klassenlader bilden eine Hierarchie (Eltern-Kind).
  • Klassen können aus Bytes geladen werden (defineClass) — relevant für Plugins/JSP usw.

Fangfrage.

Kann man mehrere Versionen derselben Klasse im JVM-Prozess laden und wie kann man das machen?

Antwort: Ja, das ist möglich, wenn man unterschiedliche Klassenlader verwendet. Klassen mit demselben FQDN, die von verschiedenen Ladern geladen werden, gelten als unterschiedliche Typen für die JVM.

Beispiel:

ClassLoader loader1 = new URLClassLoader(new URL[]{...}); ClassLoader loader2 = new URLClassLoader(new URL[]{...}); Class clazz1 = loader1.loadClass("com.example.MyClass"); Class clazz2 = loader2.loadClass("com.example.MyClass"); System.out.println(clazz1 == clazz2); // false

Beispiele für echte Fehler aufgrund mangelnder Kenntnisse über die Feinheiten des Themas.


Geschichte

In einem großen Serversystem wurden Plugins verwendet, von denen jedes über einen separaten benutzerdefinierten Klassenlader angeschlossen wurde. Die Plugins tauschten Objekte über ein gemeinsames Interface aus, das ebenfalls von seinem Klassenlader geladen wurde. Es trat eine ClassCastException bei Typumwandlungen auf, da das Interface 'PluginApi' aus dem Klassenlader des Plugins und das der Hauptanwendung als unterschiedliche Typen angesehen wurde.


Geschichte

Der Versuch, einen Servlet "hot" über einen benutzerdefinierten Klassenlader neu zu laden, führte zu Speicherlecks — die alte Klasse wurde nicht aus dem Speicher entfernt, da irgendwo in statischen Variablen ein Verweis blieb. Infolgedessen überfüllte sich PermGen schnell.


Geschichte

Ein Produkt mit Unterstützung für das dynamische Laden von Modulen verwendete implizit den Systemklassenlader, während die Entwickler versehentlich dessen Elternteil überschrieben und den Zugriff auf grundlegende Klassen (z.B. aus dem JDK) verloren. Dies führte zu Abstürzen, wenn das neue Modul die Standard-Java-Klassen wie java.sql.Driver nicht laden konnte.