Garbage Collection (GC): Was es ist, Algorithmen und Speicherbereinigung in der mobilen Entwicklung

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

Die automatische Speicherverwaltung durch Speicherbereinigung ist ein Schlüsselmechanismus der Android-Plattform, basierend auf der virtuellen Maschine ART. Laut Google Android Documentation, 2026, befreit der Garbage Collector den Entwickler von der manuellen Speicherverwaltung, indem er automatisch Objekte entfernt, auf die keine Referenzen mehr zeigen. Ohne GC würde jede Objektzuweisung einen expliziten Aufruf von free oder delete erfordern, was im Java-Ökosystem mit Millionen von Objekten pro Sekunde physikalisch unmöglich ist.

Wichtigste Erkenntnisse

  • Garbage Collection — automatischer Mechanismus zur Speicherfreigabe durch Entfernen ungenutzter Objekte in Java und Android
  • Basisalgorithmen — Mark-and-Sweep, Copying Collection und Generational Collection bestimmen die Effizienz der Sammlung
  • ART und Dalvik — zwei Implementierungen der virtuellen Android-Maschine, wobei ART (Android Runtime) Dalvik ab Android 5.0 ersetzte
  • GC-Pausen — Anhalten der Anwendungsausführung während der Sammlung — Hauptursache für Jank und Leistungsprobleme
  • GC-Optimierung — Reduzierung von Allokationen, Verwendung von Objektpools und richtige Auswahl der Sammlungstypen entlasten den Collector

Was ist Garbage Collection (GC)?

Garbage Collection (GC) ist ein automatischer Prozess zur Erkennung und Freigabe von Speicher, der von Objekten belegt wird, die vom Programm nicht mehr verwendet werden. Im Kontext der mobilen Entwicklung wird GC auf der Android-Plattform über die virtuelle Maschine ART sowie in der standardmäßigen Java Virtual Machine verwendet.

Im Gegensatz zu Sprachen mit manueller Speicherverwaltung (C, C++), bei denen der Programmierer explizit free oder delete aufrufen muss, übernimmt GC vollständig die Aufgabe, den Lebenszyklus von Objekten zu verfolgen. Der Entwickler erstellt neue Objekte über den new-Operator, während der Collector bestimmt, wann ein Objekt unerreichbar wird — das heißt, wenn keine aktiven Referenzen mehr darauf vorhanden sind.

Die Hauptmetriken der GC-Effizienz sind die Pausenzeit (pause time) und der Durchsatz (throughput). Die Pause ist der Zeitraum, in dem die Anwendungsausführung für die Sammlung angehalten wird. In einer mobilen Umgebung sind Pausen von mehr als 8–16 Millisekunden als ausgelassene Frames (Jank) wahrnehmbar.

Laut Google I/O 2019 reduzierte ART in Android 10 die typischen GC-Pausen auf 2–4 ms, was 70% weniger im Vergleich zu Dalvik in Android 4.4 entspricht. Dennoch bleibt unsachgemäße Speicherverwaltung — häufige Objektallokation in Schleifen, unnötige Erstellung temporärer Instanzen — die Hauptursache für Leistungsprobleme.

Wie funktioniert der Garbage Collector: Basisalgorithmen

Alle GC-Implementierungen in Java und Android basieren auf mehreren grundlegenden Algorithmen, die kombiniert werden, um ein Gleichgewicht zwischen Pausenzeit und Gründlichkeit der Bereinigung zu erreichen. Das Verständnis dieser Algorithmen ist für das Schreiben von GC-freundlichem Code unerlässlich.

Mark-and-Sweep

Mark-and-Sweep ist der einfachste Algorithmus, der in zwei Phasen arbeitet. In der Mark-Phase durchläuft der Collector den Objektgraphen beginnend mit den Wurzelreferenzen (Root Set) — lokalen Variablen, statischen Feldern, Thread-Stacks. Jedes erreichbare Objekt wird mit einem Live-Flag markiert. In der Sweep-Phase durchläuft der Collector den gesamten Heap und gibt den Speicher nicht markierter Objekte frei.

Der Nachteil ist die Speicherfragmentierung: Nach Sweep wechseln sich freie Bereiche mit belegten ab, was die Allokation großer Objekte erschwert. In mobilen Szenarien ist dies kritisch, da der Heap in der Regel klein ist (64–512 MB auf Android).

Copying Collection

Copying Collection teilt den Heap in zwei Halbräume (Semi-Spaces). Aktive Objekte werden lückenlos von einem Halbraum in den anderen kompakt kopiert. Nach dem Kopieren wird der alte Halbraum vollständig als frei deklariert. Der Algorithmus beseitigt die Fragmentierung vollständig, benötigt jedoch doppelt so viel Speicher.

In mobilen Umgebungen wird Copying Collection von generationalen Collectors zur schnellen Bereinigung junger Objekte verwendet, die statistisch gesehen früh sterben (schwache Generationshypothese).

Generational Collection

Generational Collection unterteilt den Heap in Generationen: Young Generation (junge Objekte) und Old Generation (alte Objekte, die mehrere Sammlungen überlebt haben). Die Sammlung der jungen Generation (Minor GC) wird häufig und schnell durchgeführt, da die meisten Objekte jung sterben. Die Sammlung der alten Generation (Major GC oder Full GC) erfolgt seltener, dauert aber länger.

java
// Demonstration des generationellen GC: Junge Objekte sterben schnell
void processItems(List<Item> items) {
    List<Result> results = new ArrayList<>();       // lebt für die gesamte Methode
    for (Item item : items) {
        Result r = new Result(item.getValue());    // stirbt sofort
        if (r.isValid()) {
            process(r);                               // r wird zu Müll
        }
    }
    saveResults(results);                             // results wechselt zu Old Gen
}

In diesem Beispiel werden Result-Objekte innerhalb einer Schleife erstellt und werden sofort zu Müll — sie sind ideale Kandidaten für Young GC. Das Objekt results lebt länger und wandert in die Old Generation. Die Trennung der Generationen ermöglicht es Minor GC, junge Objekte in Millisekunden zu bereinigen, ohne den alten Heap zu berühren.

Garbage Collection in Android: ART und Dalvik

Android hat sich von Dalvik VM zu ART (Android Runtime) weiterentwickelt, und die GC-Implementierung ist einer der Hauptunterschiede zwischen ihnen. Das Verständnis der GC-Architektur in Android hilft, Code zu schreiben, der Pausen minimiert auf realen Geräten.

EigenschaftDalvik (bis 4.4)ART (5.0+)
GC-TypMark-and-Sweep mit Concurrent MarkGenerational + Concurrent
Typische Pause10–30 ms2–4 ms
KompaktierungNein (nur Fragmentierung wächst)Ja (im Hintergrund, ohne App-Stop)
AOT-KompilierungJIT (Just-In-Time)AOT + JIT (Hybrid)

Dalvik GC

Dalvik verwendete eine Kombination aus Mark-and-Sweep mit einer konkurrierenden Phase. Concurrent Mark erlaubte der Anwendung, während der Traversierung des Objektgraphen weiterzuarbeiten, aber die Sweep-Phase erforderte das Stoppen aller Threads (Stop-The-World). Auf Geräten mit wenig RAM (512 MB — 1 GB) erreichten die Pausen 30 ms, was zu spürbaren Verzögerungen der Benutzeroberfläche führte. Außerdem kompaktierte Dalvik den Heap nicht, so dass nach längerer Nutzung die Fragmentierung zunahm und die Allokation großer Objekte (z.B. Bitmap) einen OutOfMemoryError auslösen konnte, selbst wenn insgesamt genügend freier Speicher vorhanden war.

ART GC

ART (Android Runtime) führte einen generationalen Collector mit konkurrierender Kompaktierung ein. Der Heap ist in drei Regionen unterteilt: Young, Mature (analog zur Old Generation) und Large Object Space (für Objekte größer als 12 KB). Die Sammlung der Young Region erfolgt in den meisten Fällen parallel ohne Thread-Stopps. In Android 10+ wurde Concurrent Copying eingeführt — die Kompaktierung läuft in einem Hintergrundthread ohne Stop-The-World.

Dank der ART-Architektur wurden typische GC-Pausen auf 2–4 ms reduziert, und in Szenarien mit überwiegend jungen Objekten auf 0.5–1 ms. Dies ermöglichte es Android-Geräten, stabile 60 FPS auch bei aktiven Speicheroperationen beizubehalten.

Arten von Garbage Collectors in Java

Im Java-Ökosystem gibt es mehrere GC-Implementierungen, jede mit ihrem eigenen Leistungsprofil. Für die Android-Entwicklung ist die Wahl auf ART beschränkt, aber Kenntnisse über Java GC sind beim Schreiben von serverseitigem Code für mobile Anwendungen und bei der Entwicklung mit Kotlin Multiplatform nützlich.

Serial GC

Serial GC ist ein Single-Thread-Collector mit vollständigem Anwendungsstopp (Stop-The-World). Jede Mark-, Sweep- und Compact-Operation wird von einem Thread ausgeführt. Die Leistung ist gering — wird nicht für mobile Server verwendet. Geeignet nur für kleine Anwendungen mit einem Heap von bis zu 100 MB.

Parallel GC

Parallel GC (auch bekannt als Throughput Collector) verwendet mehrere Threads für alle Sammlungsphasen. Er ist auf maximalen Durchsatz (throughput) ausgerichtet — minimiert die Zeit, die für GC im Verhältnis zur Anwendungslaufzeit aufgewendet wird. Aktiviert über das Flag -XX:+UseParallelGC in der JVM.

G1 GC

G1 (Garbage-First) GC ist der Standard-Collector in Java 9+. Der Heap ist in Regionen von 1–32 MB unterteilt. G1 sagt die Pausenzeit voraus und bemüht sich, innerhalb eines festgelegten Limits (Standard 200 ms) zu bleiben. Priorität: Regionen mit dem meisten Müll werden zuerst bereinigt (daher der Name). G1 ist effektiv für Server mit großem Heap (4–64 GB) mit vorhersagbaren Pausen.

java
// Aktivierung von G1 GC mit Zielpause von 100 ms
// java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -jar app.jar

public class MemoryMonitor {
    private static final long THRESHOLD = 512 * 1024 * 1024; // 512 MB

    public void checkHeapUsage() {
        Runtime rt = Runtime.getRuntime();
        long used = rt.totalMemory() - rt.freeMemory();
        if (used > THRESHOLD) {
            System.out.println("Heap usage exceeded threshold: " + used);
            System.out.println("Consider reducing allocations");
        }
    }
}

Die Überwachung des Heaps über Runtime ermöglicht die frühzeitige Erkennung von Speicherlecks. Wenn used bei stabilem Betrieb 80% des maximalen Heaps überschreitet — ist dies ein Signal für ein mögliches Leck oder einen übermäßigen Speicherverbrauch der Anwendung.

GC-Probleme und Speicheroptimierung in mobilen Anwendungen

Selbst moderner ART GC löst nicht alle Probleme — unsachgemäße Speichernutzung bleibt die Hauptursache für Jank und ANR (Application Not Responding). Betrachten wir die wichtigsten Szenarien und Optimierungsmethoden.

GC-Pausen und Jank

GC-Pausen — Stopps der Anwendungsthreads während der Sammlung. Auf dem Bildschirm äußert sich dies als ausgelassene Frames, wenn die Zeit zwischen zwei Frames 16.6 ms (60 FPS) überschreitet. Wenn GC 30 ms dauert, wird nur ein Frame statt zwei gezeichnet — der Benutzer sieht Ruckeln in der Benutzeroberfläche.

Die Hauptursachen für lange Pausen: eine große Anzahl lebender Objekte in der Old Generation, Heap-Fragmentierung, häufige Full GC. Zur Diagnose werden Android Studio Profiler und systrace verwendet.

Reduzierung der GC-Last

Die Hauptregel für GC-freundlichen Code ist die Minimierung der Anzahl allokierter Objekte. Jedes neue Objekt erfordert nicht nur Speicherzuweisung, sondern auch anschließende Sammlung. Selbst wenn GC schnell ist, führen 1000 zusätzliche Allokationen pro Sekunde zu 1000 Überprüfungen durch den Collector.

  • Vermeiden Sie die Objekterstellung in Schleifen — verlagern Sie die Erstellung außerhalb der Schleife, verwenden Sie lokale Variablen wieder
  • Verwenden Sie Objektpools — für Bitmap, byte[] und andere schwere Strukturen verwenden Sie Object Pool oder RecyclerView.ViewHolder
  • Bevorzugen Sie Primitive — int statt Integer, float statt Float vermeiden Autoboxing
  • Verwenden Sie SparseArray — statt HashMap<Integer, V> bietet das Android SDK SparseArray, LongSparseArray, die mit Primitive arbeiten
  • StringBuilder statt Verkettung — jede String-Verkettung erzeugt ein neues String-Objekt

Speicherlecks

Ein Speicherleck tritt auf, wenn ein Objekt erreichbar bleibt, obwohl es nicht mehr benötigt wird. GC kann ein solches Objekt nicht löschen und der Speicher wird allmählich erschöpft. Typische Ursachen: nicht abgemeldete Listener, statische Referenzen auf Activity, anonyme Klassen, die den externen Kontext erfassen, und nicht geschlossene Cursor/InputStream.

java
// Speicherleck: Anonyme Klasse hält Referenz auf Activity
public void startTask() {
    new Thread(new Runnable() {                    // hält implizit this (Activity)
        @Override
        public void run() {
            // lange Operation...
            System.out.println("Done");
        }
    }).start();
}

// Behebung: Statische verschachtelte Klasse + WeakReference
private static class TaskRunnable implements Runnable {
    private WeakReference<Activity> activityRef;

    TaskRunnable(Activity activity) {
        this.activityRef = new WeakReference<>(activity);
    }

    @Override
    public void run() {
        Activity act = activityRef.get();
        if (act != null) {
            // sichere Arbeit mit Activity
        }
    }
}

In diesem Beispiel erfasst der anonyme Runnable eine implizite Referenz auf die Activity. Solange der Thread lebt — kann die Activity nicht vom GC gesammelt werden, selbst wenn der Benutzer den Bildschirm bereits geschlossen hat. Die Korrektur mit WeakReference + statischer Klasse unterbricht diese Kette und ermöglicht die Freigabe der Activity.

Häufig gestellte Fragen

Wie unterscheidet sich GC in Android von GC in Java?

GC in Android (ART) ist ein generationaler Collector mit konkurrierender Kompaktierung, optimiert für mobile Geräte mit begrenztem Speicher. Java GC (G1, ZGC) sind serverseitige Collectors mit großen Heaps und vorhersagbaren Pausen. ART GC verwendet keine JVM-Flags — die gesamte Abstimmung erfolgt automatisch auf OS-Ebene.

Was ist Stop-The-World in GC?

Stop-The-World ist der Moment, in dem der Collector alle Anwendungsthreads anhält, um den Objektgraphen sicher zu durchlaufen oder Speicher freizugeben. Je länger das STW, desto deutlicher ist das Jank. ART hat die typische STW-Zeit auf 2–4 ms reduziert, dank seiner generationellen Architektur.

Wie erkennt man ein Speicherleck in Android?

Verwenden Sie den Android Studio Memory Profiler — er zeigt das Heap-Wachstum, die Anzahl der Allokationen und ermöglicht Heap Dumps. Für eine tiefgehende Analyse verwenden Sie LeakCanary — die Bibliothek erkennt Lecks automatisch und zeigt die Referenzkette, die die GC-Sammlung verhindert.

Wann tritt Full GC auf und warum ist es gefährlich?

Full GC ist eine vollständige Sammlung aller Heap-Generationen, einschließlich der Old Generation. In mobilen Anwendungen kann Full GC 50–200 ms dauern und zu spürbarem Jank oder ANR führen. Hauptursachen: Heap-Fragmentierung, Speicherlecks, Überschreiten der Old-Generation-Schwelle.

Wie hilft Kotlin, Speicherlecks zu vermeiden?

Kotlin bietet Koroutinen mit strukturierter Nebenläufigkeit — die Bereichsabbrüche brechen automatisch alle untergeordneten Koroutinen ab und verhindern so Lecks. Kotlin hat auch den lazy-Delegaten für die verzögerte Initialisierung und Bereichsfunktionen, die die Anzahl temporärer Objekte reduzieren.

Zusammenfassung

  • Garbage Collection — automatische Speicherverwaltung durch Entfernen unerreichbarer Objekte, Grundlage von Android Runtime
  • Mark-and-Sweep — Basisalgorithmus mit zweiphasiger Sammlung, leidet unter Heap-Fragmentierung
  • Copying Collection — beseitigt Fragmentierung durch Kopieren lebender Objekte in einen kompakten Halbraum
  • Generational GC — teilt den Heap in Generationen (Young/Old), beschleunigt die Sammlung kurzlebiger junger Objekte
  • ART in Android — generationeller Collector mit konkurrierender Kompaktierung und 2–4 ms Pausen, ersetzte Dalvik in Android 5.0
  • GC-Optimierung — Reduzierung von Allokationen, Objektpools, Primitive statt Wrapper und SparseArray statt HashMap entlasten den Collector
  • Diagnose — Android Studio Profiler, systrace und LeakCanary sind die wichtigsten Werkzeuge zur Identifizierung von Speicherproblemen

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