OutOfMemoryError in der App-Entwicklung: Was es ist, Ursachen und Präventionsmethoden

Autor: IT Sectr Veröffentlicht: 2026-03-29 Lesezeit: 9 Min.

OutOfMemoryError ist eine fatale Ausnahme, die auftritt, wenn die Java Virtual Machine (JVM) oder Android Runtime (ART) aufgrund von nicht ausreichendem Speicherplatz im Heap keinen Speicher für ein neues Objekt zuweisen kann. Laut Square Engineering werden 70 % der OutOfMemoryError in mobilen Anwendungen durch Speicherlecks verursacht, nicht durch tatsächliche Grenzüberschreitung. Das Verständnis der Ursachen von OOM ist der Schlüssel zur Stabilität der Anwendung.

Wichtige Erkenntnisse

  • OutOfMemoryError — eine Ausnahme, wenn nicht genügend Heap für ein neues Objekt vorhanden ist
  • Heap — der Speicherbereich, in dem alle Java/Kotlin-Objekte leben
  • Bitmap — der Hauptverbraucher von Heap in Android, eine typische OOM-Quelle
  • Heap Dump — ein Snapshot des Heaps zur Analyse, wer wie viel Speicher belegt
  • Behandlung von OOM erfordert das Beheben von Lecks und die Optimierung des Speicherverbrauchs

Was ist OutOfMemoryError

OutOfMemoryError (OOM) ist eine Ausnahme aus der Familie VirtualMachineError in Java/Kotlin, die die Unfähigkeit signalisiert, Speicher für ein neues Objekt zuzuweisen. Im Gegensatz zu geprüften Ausnahmen ist OOM ein Error und erfordert keine Behandlung durch catch — obwohl es technisch abgefangen werden kann. Nach dem Auftreten von OOM befindet sich die Anwendung normalerweise in einem instabilen Zustand, und es wird empfohlen, sie zu beenden.

Auf Android hat jede Anwendung ein Heap-Limit, das vom Gerätehersteller festgelegt wird. Für moderne Smartphones mit 6+ GB RAM beträgt das Limit 256–512 MB, für Budget-Geräte 128–192 MB. Wenn das Gesamtvolumen aller lebenden Objekte dieses Limit überschreitet, wirft ART einen OutOfMemoryError.

Es ist wichtig zu verstehen: OOM bedeutet nicht immer, dass dem Gerät der physische Speicher ausgegangen ist. Es bedeutet, dass die Anwendung ihr vom System festgelegtes Heap-Limit ausgeschöpft hat. Andere Anwendungen können freien Speicher haben, aber Ihre Anwendung kann ihn aufgrund der Prozessisolierung in Android nicht nutzen.

Hauptursachen von OutOfMemoryError

Fünf Szenarien führen regelmäßig zu OOM in mobilen Anwendungen. Jedes Szenario ist mit einem bestimmten Datentyp oder einer bestimmten Operation verbunden.

Bitmap ohne Skalierung

Bitmap ist der Hauptspeicherverbraucher in Android-Anwendungen. Das Laden eines FullHD-Bildes (1920 × 1080) in Originalgröße belegt 8,3 MB im ARGB_8888-Format. Wenn sich 50 solcher Bilder in einem RecyclerView befinden, sind das 415 MB, was den Heap jedes Geräts übersteigt. Das Laden von Bildern ohne inSampleSize garantiert OOM auf schwachen Geräten.

Verwenden Sie Glide oder Coil für automatische Skalierung. Diese Bibliotheken laden Bilder in einer Größe, die zur View passt, nicht zur Originalauflösung. Für die direkte Verwendung von BitmapFactory.Options wenden Sie inSampleSize an: Berechnen Sie es als Zweierpotenz, sodass die endgültige Größe 2048 × 2048 Pixel nicht überschreitet. Verwenden Sie zusätzlich RGB_565 anstelle von ARGB_8888 für Bilder ohne Transparenz — das halbiert den Speicherverbrauch.

kotlin
fun loadScaledBitmap(path: String, reqWidth: Int): Bitmap? {
    val opts = BitmapFactory.Options().apply {
        inJustDecodeBounds = true
    }
    BitmapFactory.decodeFile(path, opts)
    opts.inSampleSize = calculateSampleSize(opts.outWidth, reqWidth)
    opts.inJustDecodeBounds = false
    return BitmapFactory.decodeFile(path, opts)
}

Speicherlecks (Akkumulation)

Ein einzelnes Leck von wenigen KB verursacht kein OOM. Aber Dutzende von Lecks auf jedem Bildschirm akkumulieren sich: jeder Bildschirmübergang fügt ein Leck hinzu, der GC kann keine Objekte freigeben, und der Heap füllt sich. Ein typisches Muster: Der Benutzer öffnet und schließt den Profilbildschirm 20 Mal → der Heap wächst um 200 MB → die Anwendung stürzt mit OOM ab.

Installieren Sie LeakCanary im Projekt zur automatischen Lecksuche. Es zeigt jedes ausgelaufene Objekt mit einem genauen Stack-Trace. Nach der Behebung aller Lecks wird der Heap-Verbrauch stabil: Nach dem Schließen eines Bildschirms kehrt der Speicher auf das Basisniveau zurück.

Große Dateien im Speicher

Das Laden ganzer Dateien in byte[] ist ein direkter Weg zu OOM. Eine 50 MB große JSON-Datei erzeugt beim Parsen einen String derselben Größe plus ein DOM-Modell. In den Speicher geladene Videodateien, Audiopuffer und große Protobuf-Datensätze — alle können das Heap-Limit in einem einzigen Vorgang überschreiten.

Verarbeiten Sie große Daten mit Streams: InputStream mit einem 4–8 KB Puffer, Streaming-JSON-Parser (Jackson oder Gson mit JsonReader), MediaCodec für Videos. Rufen Sie File.readBytes() niemals bei Dateien auf, die größer als 10 % des verfügbaren Heaps sind.

Erstellen vieler Objekte in einer Schleife

Intensives Erstellen von Objekten in einer Schleife ohne zwischenzeitlichen GC kann zu OOM führen, insbesondere auf Geräten mit kleinem Heap. Beispiel: Generieren von 100.000 Objekten in einer for-Schleife, die nicht in den Heap passen, bevor der GC sie sammeln kann. Dies tritt häufiger in Spielen und Grafikeditoren auf.

Verwenden Sie Object Pool für Objekte, die massenhaft erstellt und zerstört werden. Verwenden Sie für numerische Daten Primitive (FloatArray statt List<Float>). RecyclerView mit ViewHolder Pool löst dieses Problem für UI-Komponenten.

Heap-Fragmentierung

Fragmentierung ist ein Zustand, in dem insgesamt genügend freier Speicher vorhanden ist, aber kein zusammenhängender Block für ein neues Objekt. ART kompaktiert den Heap während des GC, aber nicht immer erfolgreich. Große Arrays (Bitmap, byte[]) sind am empfindlichsten gegenüber Fragmentierung.

ART auf Android 8+ verwendet Generational GC, der die Fragmentierung durch Trennung junger und alter Objekte reduziert. Vermeiden Sie dennoch die Zuweisung von Fragmenten unterschiedlicher Größe im selben Pool — versuchen Sie stattdessen, vorab zugewiesene Puffer fester Größe zu verwenden.

Heap-Grenzen in Android

Die Heap-Grenze in Android ist keine Konstante — sie hängt vom Hersteller, Gerätemodell und der OS-Version ab. Google legt Mindestanforderungen durch das Compatibility Definition Document (CDD) fest, aber die Hersteller legen die tatsächlichen Werte fest.

GerätekategorieTypischer HeaplargeHeap
Budget (1–2 GB RAM)128–192 MB256–384 MB
Mittelklasse (3–4 GB RAM)256–384 MB512 MB
Flaggschiff (6+ GB RAM)384–512 MB768 MB–1 GB
Tablets (4+ GB RAM)256–512 MB768 MB
Wear OS32–64 MBNicht verfügbar

Sie können ein erhöhtes Limit über android:largeHeap="true" im Manifest anfordern. Verwenden Sie es mit Vorsicht: Eine Heap-Erhöhung löst das Leckproblem nicht und kann die Benutzererfahrung verschlechtern, wenn das System gezwungen ist, andere Anwendungen zu beenden, um Speicher für Ihre freizugeben. Für Wear OS ist das Heap-Limit minimal — nur 32–64 MB, largeHeap ist hier nicht verfügbar, und Speichersparen ist doppelt kritisch.

Diagnose von OutOfMemoryError

Die Diagnose von OOM erfordert die Analyse eines Heap Dumps und das Verständnis, welche Objekte Speicher verbrauchen. Android Studio bietet alle notwendigen Werkzeuge.

Schritt 1: Erfassen Sie den OOM-Moment. Klicken Sie im Android Memory Profiler auf Record memory allocations und führen Sie das Szenario aus, das den Absturz verursacht. Der Profiler zeigt einen Anstieg der Zuweisungen vor OOM. Wenn OOM nicht reproduzierbar ist, reduzieren Sie den Heap über android:smallHeap im Debug-Build oder verwenden Sie DDMS mit manuellem GC-Aufruf.

Schritt 2: Erstellen Sie einen Heap Dump bei Spitzenlast (vor OOM). Öffnen Sie den Dump in Android Studio: Der Tab Classes ist nach Retained Size sortiert. Die größten Objekte sind Bitmap, byte[], String. Überprüfen Sie für jedes Bitmap die Größe (Breite × Höhe × 4 Bytes) und den Ladepfad über den Stack Trace.

Schritt 3: Analysieren Sie die Anzahl doppelter Objekte. Wenn Sie 200 identische Fragment oder Activity sehen — das ist ein Leck. Wenn 500 Bitmap mit derselben Größe — das ist ein Bild-Caching-Problem. MAT (Memory Analyzer Tool) bietet eine tiefere Analyse mit einem Dominator Tree, der zeigt, welche Objekte 80 % des Heaps halten.

text
// Heap Dump-Befehl über adb
adb shell am dumpheap com.example.app /data/local/tmp/dump.hprof
adb pull /data/local/tmp/dump.hprof.

Präventionsstrategien für OOM

Eine umfassende OOM-Präventionsstrategie umfasst fünf Schutzebenen: von Architekturentscheidungen bis zur Produktionsüberwachung.

Architekturentscheidungen

ViewModel + Repository-Pattern trennt Daten von der UI und verhindert das Zurückhalten der View bei Bildschirmdrehung. Die ViewModel überlebt die Activity, ihre Daten gehen nicht verloren, und die View kann ohne Duplizierung von Daten im Speicher neu erstellt werden. Verwenden Sie StateFlow anstelle von LiveData für explizites Zustandsmanagement.

Bitmap- und Bildverwaltung

Glide ist eine obligatorische Bibliothek für die Arbeit mit Bildern. Sie skaliert, cached (Festplatte + Speicher) und recycelt Bitmap automatisch. Konfigurieren Sie diskCacheStrategy und skipMemoryCache für große Listen. Verwenden Sie für animierte Bilder Glide mit GIF/WebP — sie verbrauchen weniger Speicher als eine Sequenz von Bitmaps.

Produktionsüberwachung

Firebase Performance Monitoring verfolgt den Speicherverbrauch in Echtzeit. Richten Sie einen Alarm ein, wenn die Heap-Nutzung 80 % des Limits überschreitet — das ist ein Signal zur Überprüfung. Crashlytics sammelt OOM als Ausnahme und zeigt den letzten bekannten Heap-Status vor dem Absturz. Für Android 11+ verwenden Sie ApplicationExitInfo zur Erkennung von OOM-Abschlüssen.

Tests auf schwachen Geräten

Testen Sie die Anwendung unbedingt auf Geräten mit minimalem Heap (128–192 MB). Ein Emulator mit kleinem Bildschirm und kleinem Heap emuliert ein Budget-Gerät. Wenn die Anwendung auf einem solchen Gerät funktioniert, gibt es keine OOM-Probleme auf Flaggschiffen. Verwenden Sie Firebase Test Lab mit echten Geräten verschiedener Preisklassen.

kotlin
// Überprüfung des verfügbaren Heaps vor schwerer Operation
fun canAllocate(requiredBytes: Long): Boolean {
    val runtime = Runtime.getRuntime()
    val free = runtime.freeMemory()
    return free > requiredBytes * 2 // 50 % Puffer
}

Häufig gestellte Fragen

Kann OutOfMemoryError mit try-catch abgefangen werden?

Technisch ja, aber es wird nicht empfohlen. Nach OOM befindet sich die Anwendung in einem instabilen Zustand: Neue Zuweisungen können fehlschlagen und einige Objekte können teilweise erstellt sein. Die einzig sinnvolle Aktion in catch ist Protokollierung und Neustart der Activity.

Warum tritt OOM nicht auf allen Geräten auf?

Das Heap-Limit variiert zwischen Geräten. Eine Operation, die 300 MB benötigt, stürzt auf einem Gerät mit 192 MB Limit ab, gelingt aber auf einem Flaggschiff mit 512 MB. Testen Sie auf Geräten mit minimalen Spezifikationen, um OOM-Szenarien zu erkennen.

Wie wirkt sich largeHeap auf die Leistung aus?

largeHeap erhöht das Limit, beschleunigt die Anwendung aber nicht. GC-Pausen werden länger, da das Sammeln eines großen Heaps mehr Zeit in Anspruch nimmt. Das System kann Hintergrundanwendungen beenden, um Speicher bereitzustellen. Verwenden Sie largeHeap nur für Anwendungen, die objektiv viel Speicher benötigen (Kameras, Editoren).

Wie unterscheidet sich OOM von einem System-Kill?

OOM ist eine Ausnahme innerhalb einer Anwendung bei unzureichendem Heap. Ein System-Kill (Low Memory Killer) ist eine Entscheidung des Linux-Kernels, einen Prozess zu beenden, um Speicher für andere Anwendungen freizugeben. Bei einem System-Kill erhält die Anwendung keine Ausnahme — der Prozess wird einfach beendet.

Wie viel Speicher verbraucht ein Bitmap tatsächlich?

Die Formel: Breite × Höhe × bytesPerPixel. ARGB_8888 = 4 B/Pixel, RGB_565 = 2 B/Pixel. Ein FullHD-Bitmap (1920 × 1080) in ARGB_8888 = 8,3 MB. Ein 4K-Bitmap (3840 × 2160) = 33 MB. Skalieren Sie Bilder immer auf die für die Bildschirmanzeige erforderliche Größe.

Zusammenfassung

  • OutOfMemoryError — eine fatale Ausnahme, wenn das Heap-Limit der Anwendung erschöpft ist
  • Bitmap ohne Skalierung — der Hauptschuldige für OOM in mobilen Anwendungen
  • Speicherlecks verursachen 70 % der OOM durch Objektakkumulation bei jedem Übergang
  • Heap-Limit reicht von 128 MB bei Budget-Geräten bis zu 512 MB bei Flaggschiffen
  • Heap Dump mit Retained-Size-Analyse — das Hauptwerkzeug zur OOM-Diagnose
  • Glide oder Coil sind für die Arbeit mit Bildern jeder Größe obligatorisch
  • Tests auf Geräten mit minimalem Heap sind für alle Projekte ein Muss

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch