Automatisk minneshantering genom sopinsamling är den viktigaste mekanismen i Android-plattformen, baserad på den virtuella maskinen ART. Enligt Google Android Documentation, 2026, befriar sopinsamlaren utvecklaren från manuell minneshantering genom att automatiskt ta bort objekt som inte längre har några referenser. Utan GC skulle varje objekttilldelning kräva ett explicit anrop av free eller delete, vilket i Java-ekosystemet med miljontals objekt per sekund är fysiskt omöjligt.
Huvudpunkter
Garbage Collection (GC) — är en automatisk process för att upptäcka och frigöra minne som upptas av objekt som inte längre används av programmet. I sammanhanget av mobil utveckling tillämpas GC på Android-plattformen genom den virtuella maskinen ART, såväl som i den vanliga Java Virtual Machine.
Till skillnad från språk med manuell minneshantering (C, C++), där programmeraren måste explicit anropa free eller delete, tar GC helt över uppgiften att spåra objektens livscykel. Utvecklaren skapar nya objekt genom operatorn new, och insamlaren bestämmer ögonblicket när ett objekt blir oåtkomligt — det vill säga att det inte finns någon aktiv referens kvar till det.
Den huvudsakliga måttstocken för GC-effektivitet — paus tid (pause time) och genomströmning (throughput). Paus är den period då applikationens exekvering avbryts för att genomföra insamling. I en mobil miljö är pauser längre än 8–16 millisekunder märkbara som hoppade bildrutor (jank).
Enligt Google I/O 2019 minskade ART i Android 10 de typiska GC-pauserna till 2–4 ms, vilket är 70% mindre jämfört med Dalvik i Android 4.4. Ändå är felaktig hantering av minne — frekvent objektallokering i loopar, skapande av temporära instanser i onödan — den främsta orsaken till prestandaproblem.
Alla GC-implementeringar i Java och Android bygger på flera grundläggande algoritmer som kombineras för att uppnå en balans mellan paus tid och rengöringens fullständighet. Förståelse för dessa algoritmer är nödvändig för att skriva GC-vänlig kod.
Mark-and-Sweep — den enklaste algoritmen som arbetar i två faser. I Mark-fasen går insamlaren igenom objektdiagrammet, med början från rotreferenserna (root set) — lokala variabler, statiska fält, trådstackar. Varje åtkomligt objekt markeras med en live-flagga. I Sweep-fasen går insamlaren igenom hela heapen och frigör minnet för omarkerade objekt.
Nackdel — minnesfragmentering: efter Sweep växlar lediga områden med upptagna, vilket försvårar allokering av stora objekt. I mobila scenarier är detta kritiskt eftersom heapen vanligtvis är liten (64–512 MB på Android).
Copying Collection delar upp heapen i två halvutrymmen (semi-spaces). Aktiva objekt kopieras från ett halvutrymme till det andra kompakt, utan avbrott. Efter kopiering förklaras det gamla halvutrymmet helt fritt. Algoritmen eliminerar helt fragmentering, men kräver dubbelt så mycket minne.
I mobila miljöer används Copying Collection av generationsinsamlare för snabb rengöring av unga objekt, som statistiskt dör tidigt (hypotes om svag generation).
Generational Collection delar upp heapen i generationer: Young Generation (unga objekt) och Old Generation (gamla objekt som överlevt flera insamlingar). Insamling av den unga generationen (Minor GC) utförs ofta och snabbt, eftersom de flesta objekt dör unga. Insamling av den gamla generationen (Major GC eller Full GC) inträffar mer sällan men tar längre tid.
// Demonstration av generations-GC: unga objekt dör snabbt
void processItems(List<Item> items) {
List<Result> results = new ArrayList<>(); // lever hela metoden
for (Item item : items) {
Result r = new Result(item.getValue()); // dör omedelbart
if (r.isValid()) {
process(r); // r blir sopor
}
}
saveResults(results); // results flyttar till Old Gen
}
I detta exempel skapas Result-objekt inuti loopen och blir omedelbart sopor — de är idealiska kandidater för Young GC. Objektet results lever längre och migrerar till Old Generation. Separationen av generationer gör att Minor GC kan rengöra unga objekt på millisekunder utan att röra den gamla heapen.
Android har gått vägen från Dalvik VM till ART (Android Runtime), och implementeringen av GC är en av de viktigaste skillnaderna mellan dem. Förståelse för GC-arkitekturen i Android hjälper till att skriva kod som minimerar pauser på verkliga enheter.
| Egenskap | Dalvik (fram till 4.4) | ART (5.0+) |
|---|---|---|
| GC-typ | Mark-and-Sweep med Concurrent Mark | Generations + Concurrent |
| Typisk paus | 10–30 ms | 2–4 ms |
| Kompaktering | Nej (bara fragmentering ökar) | Ja (i bakgrunden, utan att stoppa appen) |
| AOT-kompilering | JIT (Just-In-Time) | AOT + JIT (hybrid) |
Dalvik använde en kombination av Mark-and-Sweep med en concurrent fas. Concurrent Mark tillät applikationen att fortsätta arbeta under genomgången av objektdiagrammet, men Sweep-fasen krävde att alla trådar stoppades (Stop-The-World). På enheter med lite RAM (512 MB — 1 GB) nådde pauserna 30 ms, vilket orsakade märkbar fördröjning av gränssnittet. Dessutom kompakterade Dalvik inte heapen, så efter längre användning ökade fragmenteringen och allokering av stora objekt (t.ex. Bitmap) kunde orsaka OutOfMemoryError även med tillräckligt totalt ledigt minne.
ART (Android Runtime) införde en generationsinsamlare med concurrent kompaktering. Heapen är uppdelad i tre regioner: Young, Mature (motsvarande Old Generation) och Large Object Space (för objekt större än 12 KB). Insamling av Young-regionen sker parallellt utan att stoppa trådar i de flesta fall. I Android 10+ uppstod Concurrent Copying — kompaktering utförs i bakgrundstråden utan Stop-The-World.
Tack vare ART-arkitekturen minskade de typiska GC-pauserna till 2–4 ms, och i scenarier med övervikt av unga objekt — till 0.5–1 ms. Detta gjorde att Android-enheter kunde leverera stabila 60 FPS även vid aktiv minnesanvändning.
I Java-ekosystemet finns flera GC-implementeringar, var och en med sin egen prestandaprofil. För Android-utveckling är valet begränsat till ART, men kunskap om Java GC är användbart när man skriver serverdelen av mobila applikationer och vid utveckling med Kotlin Multiplatform.
Serial GC — entrådig insamlare med fullständigt stopp av applikationen (Stop-The-World). Varje Mark-, Sweep- och Compact-operation utförs av en tråd. Prestandan är låg — används inte för mobila servrar. Endast lämplig för små applikationer med heap upp till 100 MB.
Parallel GC (även känd som Throughput Collector) använder flera trådar för alla insamlingsfaser. Inriktad på maximal genomströmning (throughput) — minimerar tiden som läggs på GC i förhållande till applikationens körtid. Aktiveras genom flaggan -XX:+UseParallelGC i JVM.
G1 (Garbage-First) GC — standardinsamlaren i Java 9+. Heapen är indelad i regioner om 1–32 MB. G1 förutspår paustiden och försöker hålla sig inom den inställda gränsen (standard 200 ms). Prioriteter: först rengörs regioner med störst mängd sopor (därav namnet). G1 är effektiv för servrar med stor heap (4–64 GB) och förutsägbara pauser.
// Aktivering av G1 GC med målpaus på 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("Tröskelvärdet för heap-användning överskridet: " + used);
System.out.println("Överväg att minska allokeringar");
}
}
}
Övervakning av heapen via Runtime möjliggör tidig upptäckt av minnesläckor. Om used överskrider 80% av maximal heap vid stabilt arbete — är detta en signal om möjlig läcka eller överdriven minnesförbrukning av applikationen.
Även modern ART GC löser inte alla problem — felaktig användning av minne är fortfarande den främsta orsaken till jank och ANR (Application Not Responding). Låt oss titta på de viktigaste scenarierna och optimeringsmetoderna.
GC Pauses — stopp av applikationstrådar under insamling. På skärmen visas detta som hoppade bildrutor, när tiden mellan två bildrutor överskrider 16.6 ms (60 FPS). Om GC varar 30 ms, ritas bara en bildruta istället för två — användaren ser fördröjning av gränssnittet.
De främsta orsakerna till långa pauser: stort antal levande objekt i Old Generation, heapfragmentering, frekventa Full GC. För diagnostik används Android Studio Profiler och systrace.
Huvudregeln för GC-vänlig kod — minimera antalet allokerade objekt. Varje nytt objekt kräver inte bara minnestilldelning, utan även efterföljande insamling. Även om GC är snabb, ger 1000 onödiga allokeringar per sekund 1000 kontroller till insamlaren.
En minnesläcka uppstår när ett objekt förblir åtkomligt, även om det inte längre behövs. GC kan inte ta bort ett sådant objekt och minnet tar gradvis slut. Typiska orsaker: ej avregistrerade lyssnare, statiska referenser till Activity, anonyma klasser som fångar extern kontext och oavslutade Cursor/InputStream.
// Minnesläcka: anonym klass håller referens till Activity
public void startTask() {
new Thread(new Runnable() { // håller implicit this (Activity)
@Override
public void run() {
// lång operation...
System.out.println("Klart");
}
}).start();
}
// Korrigering: statisk kapslad klass + 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) {
// säker arbete med Activity
}
}
}
I detta exempel fångar den anonyma Runnable en implicit referens till Activity. Så länge tråden lever — kan Activity inte samlas in av GC, även om användaren redan har stängt skärmen. Korrigeringen WeakReference + static class bryter denna kedja och möjliggör återanvändning av Activity.
Vanliga frågor
GC i Android (ART) är en generationsinsamlare med concurrent kompaktering, optimerad för mobila enheter med begränsat minne. Java GC (G1, ZGC) är serverinsamlare med stora heapar och förutsägbara pauser.ART GC använder inga JVM-flaggor — all konfiguration görs automatiskt på OS-nivå.
Stop-The-World — ögonblicket när insamlaren stoppar alla applikationstrådar för att säkert gå igenom objektdiagrammet eller frigöra minne. Ju längre STW, desto mer märkbar är janken. ART minskade den typiska STW-tiden till 2–4 ms tack vare generationsarkitekturen.
Använd Android Studio Memory Profiler — den visar heapens tillväxt, antal allokeringar och möjliggör Heap Dump. För djupgående analys, använd LeakCanary — biblioteket upptäcker automatiskt läckor och visar referenskedjan som hindrar GC-insamling.
Full GC — fullständig insamling av alla heapgenerationer, inklusive Old Generation. I mobila applikationer kan Full GC pågå i 50–200 ms, vilket orsakar märkbar jank eller ANR. Huvudorsaker: heapfragmentering, minnesläckor, överskridande av Old Generation-tröskeln.
Kotlin erbjuder korutiner med strukturerad samtidighet — annullering av scopet annullerar automatiskt alla underordnade korutiner och förhindrar läckor. Dessutom finns i Kotlin lazy-delegaten för lat initialisering och omfattningsoperatorer som minskar antalet tillfälliga objekt.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också