Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: LästigNullPointerException

Java sagt nicht, was null war: stimmt seit Langem nicht mehr

Eine NullPointerException nennt in Java die Referenz, die null war; die Option ist standardmäßig an. Wer nur den Stacktrace liest, übersieht es.

Aufwand:
ca. 10 Min.
Voraussetzung:
java-Kommando, Logging-Konfiguration der Anwendung, Java SE 21 Tools Reference, Beschreibung des java-Kommandos
Gilt für:
Java SE 21 (Beschreibung des java-Kommandos in der am 2026-10-15 abrufbaren Fassung), Versionsgrenze: Die Beschreibung des java-Kommandos für JDK 14 führt die Option als standardmäßig deaktiviert, die für JDK 15 als standardmäßig aktiviert; ältere Beschreibungen wurden hier nicht geprüft

Das Symptom

Der Entwickler sieht eine NullPointerException mit Zeilennummer, und in der Zeile stehen drei verkettete Aufrufe: kunde.getAdresse().getStadt().length(). Weil Java ja angeblich nicht verrät, welche Referenz null ist, baut er Debug-Ausgaben ein, zerlegt die Zeile in vier Zeilen oder setzt Haltepunkte, um den Schuldigen zu finden. Dabei steht die Antwort seit Jahren in der Meldung selbst. Der Glaubenssatz stammt aus zwei Jahrzehnten, in denen er wahr war, und wird weitergegeben, ohne die aktuelle Meldung je gelesen zu haben.

Die „Layer 8“-Wahrheit

Die Beschreibung des java-Kommandos für Java SE 21 erklärt die Option -XX:+ShowCodeDetailsInExceptionMessages so: „Enables printing of improved NullPointerException messages. When an application throws a NullPointerException, the option enables the JVM to analyze the program’s bytecode instructions to determine precisely which reference is null, and describes the source with a null-detail message.“ Die JVM liest also den Bytecode der Stelle, an der es krachte, und schreibt hin, welcher Rückgabewert, welches Feld oder welches Arrayelement null war.

Wo diese Information landet, steht im nächsten Satz: „The null-detail message is calculated and returned by NullPointerException.getMessage(), and will be printed as the exception message along with the method, filename, and line number.“ Und der entscheidende Satz der Beschreibung ist der letzte: „By default, this option is enabled.“ Niemand muss etwas einschalten. Wer heute eine NullPointerException ohne Detailtext sieht, läuft entweder auf einer sehr alten Laufzeit, hat die Option ausdrücklich abgeschaltet, oder die Exception wurde im Code mit new NullPointerException() selbst erzeugt, wofür die JVM keine Analyse macht. Ab welcher Version die Option standardmäßig aktiv ist, sagt die Beschreibung für Java SE 21 nicht; die Beschreibungen der älteren Versionen sagen es. Für JDK 14 steht bei derselben Option „By default, this option is disabled.“, für JDK 15 „By default, this option is enabled.“ Die Grenze liegt also zwischen diesen beiden Versionen; ob es die Option vor JDK 14 gab, wurde hier nicht geprüft und wird nicht behauptet.

Der richtige erste Schritt ist also, die Meldung zu lesen und nicht nur den Stacktrace. Und der zweite ist, das Logging daraufhin anzusehen: Ein Logger, der bei Exceptions nur den Typ ausgibt, verschluckt genau die Zeile, die die Arbeit erspart hätte. Das Debuggen von null-Referenzen ist nicht schwieriger geworden, es ist nur an eine Stelle gewandert, an der niemand mehr hinsieht, weil er gelernt hat, dass dort nichts steht.

Es lohnt sich, einmal bewusst eine NullPointerException zu provozieren und die erste Zeile der Ausgabe zu lesen. Dort steht, welche Methode nicht aufgerufen werden konnte, weil welcher Rückgabewert oder welches Feld null war. Wer das einmal gesehen hat, baut keine Debug-Ausgaben mehr, um eine Frage zu beantworten, die die Laufzeit schon beantwortet hat. Und wer es im Log nicht sieht, weiß ab dann, dass das Log die Zeile wegwirft, nicht die JVM.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Die vollständige Meldung lesen, nicht nur den Stacktrace

    Bei einer NullPointerException zuerst getMessage() beziehungsweise die erste Zeile der Ausgabe ansehen. Dort steht, welche Referenz null war, in der Form, dass eine Methode nicht aufgerufen werden konnte, weil ein bestimmter Rückgabewert oder ein bestimmtes Feld null ist. Erst wenn diese Zeile fehlt, lohnt sich die Suche nach dem Grund für das Fehlen.

  2. 2.

    Die Laufzeitversion prüfen

    java -version zeigt, welche Laufzeit die Anwendung tatsächlich startet. Auf einer aktuellen Laufzeit ist der Detailtext standardmäßig da; auf einer sehr alten nicht. Die Grenze liegt laut Oracles Beschreibungen des java-Kommandos zwischen JDK 14 und JDK 15: Für JDK 14 heißt es zu der Option „By default, this option is disabled.“, für JDK 15 „By default, this option is enabled.“ Wer auf JDK 14 läuft, setzt -XX:+ShowCodeDetailsInExceptionMessages selbst; wer älter läuft, hat die Option nicht.

    java -version
    
  3. 3.

    Prüfen, ob jemand die Option abgeschaltet hat

    In JAVA_TOOL_OPTIONS, in Start-Skripten und in der Container-Konfiguration nach -XX:-ShowCodeDetailsInExceptionMessages suchen. Die Option steht gelegentlich in alten Vorlagen, weil jemand einmal Ausgaben kürzen wollte. Ohne sie ist der Detailtext wieder da.

    echo "$JAVA_TOOL_OPTIONS"
    grep -r ShowCodeDetailsInExceptionMessages /etc/ /opt/app/ 2>/dev/null
    
  4. 4.

    Das Logging so einstellen, dass die Meldung ausgegeben wird

    Ein Logging, das bei Exceptions nur den Klassennamen schreibt, wirft die Antwort weg. Die Konfiguration so ändern, dass Meldung und Stacktrace ausgegeben werden, und beim Fangen von Exceptions die Exception selbst an den Logger übergeben statt nur eine eigene Beschreibung. Dann steht die null-Referenz dort, wo man sie sucht: in der ersten Zeile des Logeintrags.

Häufige Fragen (FAQ)

?Die Zeile hat drei verkettete Aufrufe. Wie finde ich heraus, welcher null war?

Indem man die Meldung der Exception liest, nicht nur den Stacktrace. Die Beschreibung des java-Kommandos sagt zur Option -XX:+ShowCodeDetailsInExceptionMessages: „When an application throws a NullPointerException, the option enables the JVM to analyze the program's bytecode instructions to determine precisely which reference is null, and describes the source with a null-detail message.“ Die Meldung nennt also die Referenz beim Namen, etwa den Rückgabewert eines bestimmten Aufrufs. Haltepunkte und Debug-Ausgaben sind dafür nicht mehr nötig.

?Muss ich die Option einschalten?

Nein. Die Beschreibung schließt mit dem Satz „By default, this option is enabled.“ Wer heute eine NullPointerException ohne Detailtext sieht, läuft entweder auf einer sehr alten Laufzeit, hat die Option ausdrücklich mit -XX:-ShowCodeDetailsInExceptionMessages abgeschaltet, oder die Exception wurde im Code mit new NullPointerException() selbst erzeugt; dafür macht die JVM keine Analyse, weil es nichts zu analysieren gibt.

?Wo steht der Detailtext genau?

In der Meldung der Exception. Laut Beschreibung gilt: „The null-detail message is calculated and returned by NullPointerException.getMessage(), and will be printed as the exception message along with the method, filename, and line number.“ Ein Logging, das nur den Typ der Exception ausgibt, verschluckt genau diese Information; ein Logging, das die Meldung und den Stacktrace ausgibt, zeigt sie in der ersten Zeile.

?Warum hält sich der Glaubenssatz so hartnäckig?

Weil er zwei Jahrzehnte lang wahr war und in dieser Zeit in Lehrbücher, Tutorials und Gewohnheiten eingegangen ist. Wer gelernt hat, dass die Meldung nichts sagt, liest sie nicht mehr und baut stattdessen Debug-Ausgaben. Die Meldung hat sich geändert, die Gewohnheit nicht. Es ist ein Rat, der einmal stimmte, und die Prüfung besteht darin, die aktuelle Meldung einmal wirklich zu lesen.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigUnsupportedClassVersionError

Java: UnsupportedClassVersionError

Das Programm wurde mit einem neueren Java kompiliert, als es ausführt? Diese Meldung nennt sogar die Versionsnummern — man muss sie nur übersetzen.

SWLästig

jcmd findet keine Java-Prozesse

jcmd -l listet nichts oder nur sich selbst, obwohl die JVM läuft. Schuld ist fast immer der falsche Benutzer – und sudo macht es schlimmer, nicht besser.

SWSystemzerstörendjava.lang.OutOfMemoryError: Java heap space

OutOfMemoryError: Java heap space

Der Java-Prozess läuft gegen sein Speicherlimit. Mehr Heap zu geben ist oft nur ein Pflaster – meist steckt ein Speicherleck dahinter.

SWSystemzerstörendjava.lang.OutOfMemoryError: Metaspace

java.lang.OutOfMemoryError: Metaspace

Der Heap ist halb leer, die JVM stirbt trotzdem. Metaspace liegt im nativen Speicher und hat eine eigene Grenze – ein größerer Heap hilft nicht.