Übersicht über die Speicherverwaltung

Die virtuelle Maschine von Android Runtime (ART) und der virtuellen Dalvik-Maschine verwenden Paging und Arbeitsspeicherzuordnung (mmapping) zur Verwaltung des Arbeitsspeichers. Das bedeutet, dass jeder Speicher, der von einer App geändert wird, entweder durch Zuweisen neuer Objekte oder durch Berühren zugeordneter Seiten, im RAM verbleibt und nicht ausgelagert werden kann. Die einzige Möglichkeit, Arbeitsspeicher von einer Anwendung freizugeben, besteht darin, die in der App enthaltenen Objektverweise freizugeben, um den Arbeitsspeicher für die automatische Speicherbereinigung verfügbar zu machen. Dies ist mit einer Ausnahme: Alle Dateien, die unverändert eingefügt wurden (z. B. Code), können aus dem RAM entfernt werden, wenn das System diesen Speicher an anderer Stelle verwenden möchte.

Auf dieser Seite wird erläutert, wie Android App-Prozesse und Arbeitsspeicherzuweisung verwaltet. Weitere Informationen zum effizienteren Verwalten des Arbeitsspeichers in Ihrer Anwendung finden Sie unter Arbeitsspeicher der Anwendung verwalten.

Automatische Speicherbereinigung

Eine verwaltete Speicherumgebung wie die virtuelle Maschine ART oder Dalvik erfasst jede Arbeitsspeicherzuweisung. Sobald der Speicher feststellt, dass ein Teil des Speichers nicht mehr vom Programm verwendet wird, wird er ohne Zutun des Programmierers wieder auf den Heap freigegeben. Der Mechanismus zur Rückgewinnung von nicht verwendetem Arbeitsspeicher in einer verwalteten Speicherumgebung wird als automatische Speicherbereinigung bezeichnet. Die automatische Speicherbereinigung verfolgt zwei Ziele: Datenobjekte in einem Programm finden, auf die in Zukunft nicht mehr zugegriffen werden kann, und die von diesen Objekten verwendeten Ressourcen zurückzugewinnen.

Der Arbeitsspeicher-Heap von Android ist seit Generationen geprägt. Das bedeutet, dass es je nach erwarteter Lebensdauer und Größe eines zugewiesenen Objekts verschiedene Buckets mit Zuweisungen gibt. Kürzlich zugewiesene Objekte gehören beispielsweise zur Jüngeren Generation. Wenn ein Objekt lange genug aktiv bleibt, kann es zu einer älteren Generation und dann zu einer dauerhaften Generation hochgestuft werden.

Jede Heap-Generierung hat eine eigene Obergrenze für den Arbeitsspeicher, den Objekte belegen können. Jedes Mal, wenn sich eine Generation füllt, führt das System ein automatisches Speicherbereinigungsereignis aus, um Arbeitsspeicher freizugeben. Die Dauer der automatischen Speicherbereinigung hängt davon ab, welche Objektgeneration erfasst wird und wie viele aktive Objekte in jeder Generation vorhanden sind.

Auch wenn die automatische Speicherbereinigung recht schnell sein kann, kann sie die Leistung Ihrer Anwendung beeinträchtigen. In der Regel steuern Sie nicht, wann ein Ereignis für die automatische Speicherbereinigung innerhalb Ihres Codes auftritt. Das System hat eine Reihe von Kriterien, mit denen festgelegt wird, wann die automatische Speicherbereinigung durchgeführt werden soll. Wenn die Kriterien erfüllt sind, beendet das System die Ausführung des Prozesses und beginnt mit der automatischen Speicherbereinigung. Wenn die automatische Speicherbereinigung mitten in einer intensiven Verarbeitungsschleife, z. B. in einer Animation oder während der Musikwiedergabe, erfolgt, kann sich dies auf die Verarbeitungszeit auswirken. Durch diesen Anstieg kann die Codeausführung in Ihrer App möglicherweise den empfohlenen Grenzwert von 16 ms überschreiten, um ein effizientes und reibungsloses Frame-Rendering zu ermöglichen.

Darüber hinaus kann Ihr Codeablauf Aufgaben ausführen, die dazu führen, dass Ereignisse der automatischen Speicherbereinigung häufiger auftreten oder länger dauern als normal. Wenn Sie beispielsweise mehrere Objekte im innersten Teil einer for-Schleife während jedes Frames einer Alpha-Blending-Animation zuordnen, kann dies Ihren Arbeitsspeicher-Heap mit vielen Objekten überlasten. In diesem Fall führt die automatische Speicherbereinigung mehrere Ereignisse für die automatische Speicherbereinigung aus und kann die Leistung Ihrer Anwendung beeinträchtigen.

Weitere allgemeine Informationen zur automatischen Speicherbereinigung finden Sie unter automatische Speicherbereinigung.

Erinnerung teilen

Damit alle Anforderungen des Arbeitsspeichers erfüllt werden können, versucht Android, RAM-Seiten für mehrere Prozesse freizugeben. Dazu stehen Ihnen folgende Möglichkeiten zur Verfügung:

  • Jeder Anwendungsprozess ist von einem bestehenden Prozess namens Zygote abgespalten. Der Zygote-Prozess beginnt, wenn das System bootet und gemeinsamen Framework-Code und -Ressourcen (z. B. Aktivitätsthemen) lädt. Zum Starten eines neuen Anwendungsprozesses verzweigt das System den Zygote-Prozess. Anschließend wird der Anwendungscode geladen und im neuen Prozess ausgeführt. Mit diesem Ansatz können die meisten der für den Framework-Code und die Ressourcen zugewiesenen RAM-Seiten von allen Anwendungsprozessen gemeinsam genutzt werden.
  • Die meisten statischen Daten werden in einen Prozess eingebunden. Mit dieser Technik können Daten von Prozessen gemeinsam genutzt und bei Bedarf ausgelagert werden. Beispiele für statische Daten sind: Dalvik-Code (durch Einfügen in eine vorab verknüpfte Datei .odex für direktes Mmapping), App-Ressourcen (indem die Ressourcentabelle eine Struktur ist, die mappiert werden kann, und durch Ausrichten der ZIP-Einträge des APK) sowie traditionelle Projektelemente wie nativer Code in .so-Dateien.
  • An vielen Stellen nutzt Android denselben dynamischen RAM für alle Prozesse unter Verwendung explizit zugewiesener Speicherregionen (entweder mit ashmem oder gralloc). Beispielsweise nutzen Fensteroberflächen gemeinsamen Speicher zwischen der App und dem Bildschirmcompositor und Cursorzwischenspeicher nutzen gemeinsam genutzten Speicher zwischen dem Contentanbieter und dem Client.

Aufgrund der umfassenden Nutzung von gemeinsam genutztem Speicher ist die Ermittlung, wie viel Speicher die App nutzt, mit Bedacht erforderlich. Verfahren zur richtigen Ermittlung der Arbeitsspeichernutzung Ihrer Anwendung finden Sie unter RAM-Nutzung untersuchen.

App-Arbeitsspeicher zuweisen und freigeben

Der Dalvik-Heap ist auf einen einzelnen virtuellen Speicherbereich für jeden Anwendungsprozess beschränkt. Dies definiert die logische Heap-Größe, die nach Bedarf wachsen kann, jedoch nur bis zu einem Grenzwert, den das System für jede Anwendung definiert.

Die logische Größe des Heaps ist nicht dasselbe wie die Menge des physischen Arbeitsspeichers, der vom Heap belegt wird. Bei der Prüfung des Heaps Ihrer App berechnet Android einen Wert namens Proportional Set size (PSS), der sowohl schmutzige als auch saubere Seiten berücksichtigt, die mit anderen Prozessen geteilt werden, jedoch nur in einem Betrag, der proportional dazu ist, wie viele Apps diesen RAM nutzen. Diese Gesamtsumme (PSS) wird vom System als Ihr physischer Arbeitsspeicherbedarf betrachtet. Weitere Informationen zu PSS finden Sie im Leitfaden RAM-Nutzung untersuchen.

Der Dalvik-Heap verdichtet die logische Größe des Heaps nicht, was bedeutet, dass Android den Heap nicht defragmentiert, um den Bereich zu schließen. Android kann die logische Heap-Größe nur verkleinern, wenn am Ende des Heaps ungenutzter Speicherplatz vorhanden ist. Das System kann jedoch den vom Heap belegten physischen Arbeitsspeicher reduzieren. Nach der automatischen Speicherbereinigung durchläuft Dalvik den Heap, findet nicht verwendete Seiten und gibt diese Seiten dann mithilfe von Madvise an den Kernel zurück. Daher sollten paarweise Zuweisungen und Freigaben großer Blöcke dazu führen, dass der gesamte (oder fast alle) physische Arbeitsspeicher zurückgefordert wird. Die Rückgewinnung von Arbeitsspeicher aus kleinen Zuweisungen kann jedoch viel weniger effizient sein, da die für eine kleine Zuweisung verwendete Seite möglicherweise noch für etwas anderes freigegeben wird, das noch nicht freigegeben wurde.

App-Arbeitsspeicher einschränken

Android legt für jede Anwendung ein festes Limit für die Heap-Größe fest, um eine funktionsfähige Multitasking-Umgebung aufrechtzuerhalten. Das genaue Limit für die Heap-Größe variiert je nach verfügbarem RAM auf dem Gerät. Wenn Ihre Anwendung die Heap-Kapazität erreicht hat und versucht, mehr Arbeitsspeicher zuzuweisen, kann sie ein OutOfMemoryError erhalten.

In einigen Fällen kann es sinnvoll sein, das System abzufragen, um genau zu ermitteln, wie viel Heap-Speicherplatz auf dem aktuellen Gerät verfügbar ist, z. B. um festzustellen, wie viele Daten sicher in einem Cache gespeichert werden können. Sie können das System nach dieser Zahl abfragen, indem Sie getMemoryClass() aufrufen. Diese Methode gibt eine Ganzzahl zurück, die die Anzahl der Megabyte angibt, die für den Heap der Anwendung verfügbar sind.

Apps wechseln

Wenn Nutzer zwischen Apps wechseln, speichert Android Apps, die nicht im Vordergrund – also für den Nutzer sichtbar – nicht im Vordergrund stehen, oder die einen Dienst im Vordergrund wie die Musikwiedergabe ausführen, in einem Cache. Wenn ein Nutzer beispielsweise zum ersten Mal eine Anwendung startet, wird ein Prozess für diese erstellt. Verlässt der Nutzer die Anwendung jedoch, wird dieser Prozess nicht beendet. Der Prozess wird vom System im Cache gespeichert. Wenn der Nutzer später zur Anwendung zurückkehrt, verwendet das System den Prozess wieder, wodurch die Anwendung schneller wechselt.

Wenn Ihre Anwendung einen im Cache gespeicherten Prozess hat und Ressourcen beibehält, die sie derzeit nicht benötigt, wirkt sich Ihre Anwendung auf die Gesamtleistung des Systems aus, auch wenn sie vom Nutzer nicht verwendet wird. Wenn dem System nur noch wenige Ressourcen wie der Arbeitsspeicher zur Verfügung stehen, werden Prozesse im Cache beendet. Das System berücksichtigt auch Prozesse, die viel Arbeitsspeicher belegen, und kann diese beenden, um RAM freizugeben.

Hinweis:Je weniger Arbeitsspeicher die Anwendung verbraucht, während sie sich im Cache befindet, desto höher ist die Wahrscheinlichkeit, dass sie nicht abgebrochen wird und schnell fortgesetzt werden kann. Abhängig von den sofortigen Systemanforderungen ist es jedoch möglich, dass im Cache gespeicherte Prozesse jederzeit unabhängig von ihrer Ressourcennutzung beendet werden.

Weitere Informationen dazu, wie Prozesse im Cache gespeichert werden, während sie nicht im Vordergrund ausgeführt werden, und wie Android entscheidet, welche Prozesse beendet werden können, finden Sie in der Anleitung Prozesse und Threads.

Gedächtnistest

Obwohl sie auf High-End-Geräten weniger häufig auftreten, können sie auch bei Nutzern von Geräten mit wenig RAM, z. B. auf Geräten mit Android (Go-Edition) zu Problemen führen. Es ist wichtig, diese arbeitsspeicherbelastete Umgebung zu reproduzieren, damit Sie Instrumentierungstests schreiben können, um das Anwendungsverhalten zu überprüfen und die Nutzerfreundlichkeit auf Geräten mit wenig Arbeitsspeicher zu verbessern.

Stressiger Anwendungstest

Stressful Application Test (stressapptest) ist ein Speicherschnittstellentest, mit dem Sie realistische Situationen mit hoher Last erstellen können, um verschiedene Speicher- und Hardwareeinschränkungen für Ihre Anwendung zu testen. Sie können damit Zeit- und Speicherlimits definieren und Instrumentierungen dafür erstellen, mit denen Sie reale Situationen mit großem Arbeitsspeicher prüfen können. Verwenden Sie beispielsweise den folgenden Satz von Befehlen, um die statische Bibliothek in Ihr Datendateisystem zu übertragen, sie ausführbar zu machen und einen 20 Sekunden langen Belastungstest mit einer Größe von 990 MB durchzuführen:
    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

Weitere Informationen zur Installation des Tools, zu gängigen Argumenten und zur Fehlerbehandlung finden Sie in der Dokumentation zu stressapptest.

Beobachtungen zu Stressapptest

Mit Tools wie stressapptest können Arbeitsspeicherzuweisungen angefordert werden, die größer als kostenlos verfügbar sind. Diese Art von Anfrage kann verschiedene Benachrichtigungen auslösen, über die Sie sich auf Entwicklungsseite informieren sollten. Die drei wichtigsten Benachrichtigungen, die aufgrund einer geringen Arbeitsspeicherverfügbarkeit ausgelöst werden können, sind:
  • SIGABRT: Dies ist ein schwerwiegender, nativer Absturz für Ihren Prozess, weil Zuweisungen angefordert werden, die größer als der kostenlose Arbeitsspeicher sind, während das System bereits unter Arbeitsspeicherauslastung steht.
  • SIGQUIT: Erzeugt einen zentralen Arbeitsspeicher-Dump und beendet den Prozess, wenn dies von Ihrem Instrumentierungstest erkannt wurde.
  • TRIM_MEMORY_EVENTS: Diese Callbacks sind unter Android 4.1 (API-Level 16) und höher verfügbar und liefern detaillierte Speicherbenachrichtigungen für deinen Prozess.