Garbage Collection (GC): vad är det, algoritmer och sopinsamling i mobil utveckling

Författare: IT Sectr Publicerad: 2026-03-29 Lästid: 10 min

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 — automatisk mekanism för minnesfrigöring genom borttagning av oanvända objekt i Java och Android
  • Grundläggande algoritmer — Mark-and-Sweep, Copying Collection och Generational Collection bestämmer effektiviteten av insamlingen
  • ART och Dalvik — två implementeringar av Androids virtuella maskin, där ART (Android Runtime) ersatte Dalvik från och med Android 5.0
  • GC Pauses — avbrott i applikationens exekvering under insamling — den främsta orsaken till jank och prestandaproblem
  • GC-optimering — minskning av allokeringar, användning av objektpooler och korrekt val av Collection-typer minskar belastningen på insamlaren

Vad är Garbage Collection (GC)?

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.

Hur fungerar sopinsamlaren: grundläggande algoritmer

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

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

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

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.

java
// 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.

Garbage Collection i Android: ART och Dalvik

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.

EgenskapDalvik (fram till 4.4)ART (5.0+)
GC-typMark-and-Sweep med Concurrent MarkGenerations + Concurrent
Typisk paus10–30 ms2–4 ms
KompakteringNej (bara fragmentering ökar)Ja (i bakgrunden, utan att stoppa appen)
AOT-kompileringJIT (Just-In-Time)AOT + JIT (hybrid)

Dalvik GC

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 GC

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.

Typer av sopinsamlare i Java

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

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

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 GC

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.

java
// 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.

GC-problem och minnesoptimering i mobila applikationer

Ä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 och Jank

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.

Minskning av GC-belastning

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.

  • Undvik att skapa objekt i loopar — placera skapandet utanför loopen, återanvänd lokala variabler
  • Använd objektpooler — för Bitmap, byte[] och andra tunga strukturer, använd Object Pool eller RecyclerView.ViewHolder
  • Föredra primitiva typer — int istället för Integer, float istället för Float undviker autoboxning
  • Använd SparseArray — istället för HashMap<Integer, V> i Android SDK finns SparseArray, LongSparseArray som arbetar med primitiva typer
  • StringBuilder istället för konkatenering — varje strängsammanslagning skapar ett nytt String-objekt

Minnesläckor

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.

java
// 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

Hur skiljer sig GC i Android från GC i Java?

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å.

Vad är Stop-The-World i GC?

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.

Hur upptäcker man en minnesläcka i Android?

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.

När inträffar Full GC och varför är det farligt?

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.

Hur hjälper Kotlin att undvika minnesläckor?

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

  • Garbage Collection — automatisk minneshantering genom borttagning av oåtkomliga objekt, grunden för Android Runtime
  • Mark-and-Sweep — grundläggande algoritm med tvåfasinsamling, lider av heapfragmentering
  • Copying Collection — eliminerar fragmentering genom att kopiera levande objekt till ett kompakt halvutrymme
  • Generational GC — delar upp heapen i generationer (Young/Old), snabbar upp insamling av unga kortlivade objekt
  • ART i Android — generationsinsamlare med concurrent kompaktering och pauser på 2–4 ms, som ersatte Dalvik i Android 5.0
  • GC-optimering — minskning av allokeringar, objektpooler, primitiva typer istället för wrapper och SparseArray istället för HashMap minskar insamlarens belastning
  • Diagnostik — Android Studio Profiler, systrace och LeakCanary är de främsta verktygen för att identifiera minnesproblem

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.

Diskutera projektet

Läs också