EMZETT.
Login

Errors

Kurz: Schwerwiegende Probleme, die ein Java-Programm normalerweise nicht selbst abfangen sollte — z. B. OutOfMemoryError oder StackOverflowError, beide Unterklassen von java.lang.Error.

Genauer: Java unterscheidet strikt zwischen Error (Problem auf JVM-Ebene, meist nicht sinnvoll behandelbar) und Exceptions (Problem auf Programmebene, das man gezielt abfangen und behandeln kann). Beide erben von der gemeinsamen Oberklasse Throwable.

Im Detail

Throwable
├── Error                    (JVM-Ebene, i. d. R. nicht sinnvoll abfangbar)
│   ├── OutOfMemoryError      Heap-Speicher erschöpft
│   └── StackOverflowError    zu tiefe/endlose Rekursion
└── Exception                 (Programmebene, gezielt behandelbar)
    ├── IOException           (checked - Compiler erzwingt Behandlung)
    └── RuntimeException       (unchecked)
        ├── NullPointerException
        ├── ArrayIndexOutOfBoundsException
        └── ArithmeticException

Ein StackOverflowError entsteht typischerweise durch Rekursion ohne (oder mit fehlerhaftem) Abbruchfall — jeder Methodenaufruf legt einen neuen Stack-Frame an, bis der reservierte Speicher für den Aufrufstapel voll ist. Ein OutOfMemoryError tritt auf, wenn der Heap (wo Objekte liegen) komplett ausgeschöpft ist, oft durch Speicherlecks (Objekte, die referenziert bleiben, obwohl sie nicht mehr gebraucht werden, und deshalb nie vom Garbage Collector eingesammelt werden). Technisch ist es zwar MÖGLICH, catch (Error e) zu schreiben, aber in den allermeisten Fällen sinnlos: Ist der Heap voll oder der Stack übergelaufen, ist die JVM oft schon in einem so instabilen Zustand, dass auch der catch-Block selbst nicht mehr zuverlässig laufen kann — daher die Konvention, Error grundsätzlich NICHT abzufangen und stattdessen die Ursache (endlose Rekursion, Speicherleck) zu beheben.

Typische Ursachen für StackOverflowError

Neben fehlerhafter Rekursion ohne Abbruchfall kann ein StackOverflowError auch bei KORREKTER, aber zu tiefer Rekursion auftreten — z. B. beim rekursiven Verarbeiten einer sehr langen Liste (mehrere hunderttausend Elemente), wenn jede Rekursionsebene einen eigenen Stack-Frame verbraucht. Hier hilft entweder eine iterative Umsetzung mit einer expliziten Schleife statt Rekursion, oder — falls verfügbar — eine Endrekursions-Optimierung, die Java (anders als z. B. Scala) allerdings NICHT garantiert unterstützt, selbst wenn der rekursive Aufruf technisch die letzte Anweisung ist.

// Gefährlich bei sehr langen Listen: rekursive Summierung
int summeRekursiv(List<Integer> liste, int index) {
    if (index >= liste.size()) return 0;
    return liste.get(index) + summeRekursiv(liste, index + 1); // ein Stack-Frame pro Element
}
 
// Robuster: iterative Variante ohne Rekursionstiefe-Limit
int summeIterativ(List<Integer> liste) {
    int summe = 0;
    for (int wert : liste) summe += wert;
    return summe;
}

OutOfMemoryError gezielt diagnostizieren

Bei einem OutOfMemoryError in Produktion hilft der reine Fehler allein selten weiter — die JVM lässt sich mit dem Flag -XX:+HeapDumpOnOutOfMemoryError so konfigurieren, dass sie beim Auftreten automatisch einen Heap-Dump schreibt, der sich anschließend mit Tools wie Eclipse MAT analysieren lässt, um genau zu sehen, welche Objekte den Speicher belegen und warum sie nicht vom Garbage Collector eingesammelt werden konnten.

Siehe auch: Exceptions, Debugging, Error Codes