De Android Runtime (ART) en de Dalvik virtuele machine gebruiken paging en memory-mapping (mmapping) om het geheugen te beheren. Dit betekent dat al het geheugen dat een app wijzigt – door nieuwe objecten toe te wijzen of door mmapped pages aan te raken – in het RAM blijft en niet kan worden uitgepaged. De enige manier om geheugen van een app vrij te maken is door objectreferenties die de app heeft vrij te maken, waardoor het geheugen beschikbaar wordt voor de vuilnisman. Dat is met één uitzondering: alle bestanden die zonder wijziging zijn ingebouwd, zoals code, kunnen uit het RAM worden gepaged als het systeem dat geheugen elders wil gebruiken.
Deze pagina legt uit hoe Android app processen en geheugentoewijzing beheert. Voor meer informatie over hoe u geheugen efficiënter kunt beheren in uw app, zie Het geheugen van uw app beheren.
Garbage collection
Een beheerde geheugenomgeving, zoals de virtuele machine ART of Dalvik, houdt elke geheugentoewijzing bij. Zodra wordt vastgesteld dat een stuk geheugen niet langer door het programma wordt gebruikt, wordt het teruggezet op de heap, zonder enige tussenkomst van de programmeur. Het mechanisme voor het terugwinnen van ongebruikt geheugen in een beheerde geheugenomgeving staat bekend als garbage collection. Garbage collection heeft twee doelen: het vinden van data objecten in een programma die in de toekomst niet kunnen worden benaderd; en het terugwinnen van de middelen die worden gebruikt door deze objecten.
Android’s geheugen heap is een generatie heap, wat betekent dat er verschillende emmers van toewijzingen zijn die het bijhoudt, gebaseerd op de verwachte levensduur en de grootte van een object dat wordt toegewezen. Bijvoorbeeld, recent toegewezen objecten behoren tot de Jonge generatie. Wanneer een object lang genoeg actief blijft, kan het worden gepromoveerd naar een oudere generatie, gevolgd door een permanente generatie.
Elke heap generatie heeft zijn eigen specifieke bovengrens voor de hoeveelheid geheugen die objecten daar kunnen innemen. Telkens wanneer een generatie vol begint te raken, voert het systeem een vuilnisophaalactie uit in een poging geheugen vrij te maken. De duur van de garbage collection hangt af van welke generatie objecten het aan het verzamelen is en hoeveel actieve objecten er in elke generatie zijn.
Hoewel garbage collection vrij snel kan zijn, kan het toch de prestaties van je app beïnvloeden. Over het algemeen heb je vanuit je code geen controle over wanneer een vuilnisophaalactie plaatsvindt. Het systeem heeft een aantal criteria om te bepalen wanneer het vuilnis moet worden opgehaald. Als aan de criteria is voldaan, stopt het systeem met het uitvoeren van het proces en begint het met de vuilnisophaalactie. Als de vuilnisophaling midden in een intensieve verwerkingscyclus plaatsvindt, zoals een animatie of tijdens het afspelen van muziek, kan dit de verwerkingstijd verlengen. Deze toename kan ertoe leiden dat de uitvoering van code in uw app de aanbevolen drempel van 16 ms voor efficiënte en vloeiende frame-rendering overschrijdt.
Daarnaast kan uw codestroom werkzaamheden uitvoeren die ertoe leiden dat vuilnisophaalgebeurtenissen vaker voorkomen of dat ze langer duren dan normaal. Als je bijvoorbeeld meerdere objecten toewijst in het binnenste deel van een for-lus tijdens elk frame van een alpha-blending animatie, kun je de geheugenhoop vervuilen met een heleboel objecten. In dat geval voert de garbage collector meerdere garbage collection events uit en kan de performance van uw app verslechteren.
Voor meer algemene informatie over garbage collection, zie Garbage collection.
Geheugen delen
Om alles wat het nodig heeft in het RAM te passen, probeert Android RAM-pagina’s te delen tussen processen. Dat kan op de volgende manieren:
- Elk app-proces wordt gevorkt van een bestaand proces genaamd Zygote. Het Zygote-proces start wanneer het systeem opstart en laadt gemeenschappelijke frameworkcode en bronnen (zoals activiteitsthema’s). Om een nieuw app proces te starten, fork het systeem het Zygote proces en laadt en draait de code van de app in het nieuwe proces. Door deze aanpak kunnen de meeste RAM-pagina’s die zijn toegewezen voor frameworkcode en hulpbronnen, worden gedeeld door alle app-processen.
- De meeste statische gegevens worden in een proces gemapt. Met deze techniek kunnen gegevens worden gedeeld tussen processen, en kunnen ze ook worden uitgepaged wanneer dat nodig is. Voorbeeld statische gegevens omvatten: Dalvik-code (door deze in een vooraf gekoppeld
.odex
-bestand te plaatsen voor directe mmapping), app-bronnen (door de resourcetabel te ontwerpen als een structuur die kan worden mmapped en door de zip-items van de APK uit te lijnen), en traditionele projectelementen zoals native code in.so
-bestanden. - Op veel plaatsen deelt Android dezelfde dynamische RAM tussen processen met behulp van expliciet toegewezen gedeelde geheugen regio’s (hetzij met ashmem of gralloc). Bijvoorbeeld, venster oppervlakken gebruiken gedeeld geheugen tussen de app en scherm compositor, en cursor buffers gebruiken gedeeld geheugen tussen de content provider en client.
Door het uitgebreide gebruik van gedeeld geheugen, vereist het bepalen van de hoeveelheid geheugen die je app gebruikt zorgvuldigheid. Technieken om het geheugengebruik van uw app goed te bepalen, worden besproken in Onderzoek naar uw RAM-gebruik.
App-geheugen toewijzen en terugwinnen
De Dalvik-heap is beperkt tot een enkel virtueel geheugenbereik voor elk app-proces. Dit definieert de logische heap grootte, die kan groeien als het nodig is, maar slechts tot een limiet die het systeem definieert voor elke app.
De logische grootte van de heap is niet hetzelfde als de hoeveelheid fysiek geheugen gebruikt door de heap. Bij het inspecteren van de heap van uw app, Android berekent een waarde genaamd de Proportionele Set Grootte (PSS), die rekening houdt met zowel vuile en schone pagina’s die worden gedeeld met andere processen-maar alleen in een hoeveelheid die evenredig is met hoeveel apps dat RAM delen. Dit (PSS) totaal is wat het systeem beschouwt als uw fysieke geheugen footprint. Voor meer informatie over PSS, zie de Investigating Your RAM Usage gids.
De Dalvik heap comprimeert niet de logische grootte van de heap, wat betekent dat Android de heap niet defragmenteert om ruimte op te ruimen. Android kan alleen de logische heap-grootte verkleinen wanneer er ongebruikte ruimte is aan het einde van de heap. Het systeem kan echter nog steeds het fysieke geheugen dat wordt gebruikt door de heap verkleinen. Na garbage collection, loopt Dalvik de heap af en vindt ongebruikte pagina’s, en retourneert die pagina’s dan aan de kernel met behulp van madvise. Dus, gekoppelde allocaties en deallocaties van grote chunks zouden moeten resulteren in het terugwinnen van al (of bijna al) het gebruikte fysieke geheugen. Echter, het terugwinnen van geheugen van kleine toewijzingen kan veel minder efficiënt zijn, omdat de pagina die wordt gebruikt voor een kleine toewijzing nog steeds gedeeld kan worden met iets anders dat nog niet is vrijgemaakt.
Restrict app geheugen
Om een functionele multi-tasking omgeving te behouden, stelt Android een harde limiet aan de heap grootte voor elke app. De exacte heap grootte limiet varieert tussen apparaten op basis van hoeveel RAM het apparaat in totaal beschikbaar heeft. Als uw app de heap capaciteit heeft bereikt en probeert meer geheugen toe te wijzen, kan het een OutOfMemoryError
.
In sommige gevallen wilt u misschien het systeem vragen om precies te bepalen hoeveel heap ruimte u beschikbaar heeft op het huidige apparaat-bijvoorbeeld om te bepalen hoeveel gegevens veilig in een cache kunnen worden bewaard. U kunt het systeem om dit getal vragen door getMemoryClass()
aan te roepen. Deze methode retourneert een geheel getal dat het aantal megabytes aangeeft dat beschikbaar is voor de heap van uw app.
Switch apps
Als gebruikers tussen apps wisselen, bewaart Android apps die niet op de voorgrond staan – dat wil zeggen, niet zichtbaar zijn voor de gebruiker of een voorgronddienst draaien zoals het afspelen van muziek – in een cache. Bijvoorbeeld, wanneer een gebruiker voor het eerst een app start, wordt er een proces voor aangemaakt; maar wanneer de gebruiker de app verlaat, wordt dat proces niet afgesloten. Het systeem houdt het proces in de cache. Als de gebruiker later terugkeert naar de app, hergebruikt het systeem het proces, waardoor de app sneller schakelt.
Als uw app een proces in de cache heeft en bronnen vasthoudt die hij op dat moment niet nodig heeft, dan beïnvloedt uw app – zelfs als de gebruiker hem niet gebruikt – de algehele prestaties van het systeem. Als het systeem te weinig bronnen zoals geheugen heeft, doodt het processen in de cache. Het systeem houdt ook rekening met processen die het meeste geheugen vasthouden en kan deze beëindigen om RAM vrij te maken.
Opmerking: Hoe minder geheugen uw app in de cache gebruikt, des te groter is de kans dat deze niet wordt gedood en snel kan worden hervat. Echter, afhankelijk van de onmiddellijke systeemvereisten, is het mogelijk voor processen in de cache om op elk gewenst moment te worden beëindigd, ongeacht hun resource-gebruik.
Voor meer informatie over hoe processen worden gecached terwijl ze niet op de voorgrond draaien en hoe Android beslist welke kunnen worden gedood, zie de Processen en Threads gids.