En introduktion til hukommelsesstyring og hukommelseslækager på Android

Det er værd at huske på, at selvom dette værktøj kan være meget nyttigt til at finde referencer til en mistænkt lækage, kan det være ret svært og komplekst at bruge til at finde ukendte lækager og kræver en del analyse. Når det er sagt, hvis du mestrer det – er det et godt værktøj at have under bæltet!

LeakCanary

Billede fra LeakCanary

En anden måde at finde hukommelseslækager på er ved at bruge Leak Canary, et bibliotek skabt af Square, som hjælper dig med at opdage hukommelseslækager. Det fungerer ved hjælp af en ObjectWatcher-klasse, der indeholder svage referencer til ødelagte objekter i heap’en. Hvis referencen ikke bliver slettet inden for de følgende fem sekunder, og Garbage Collector har kørt, anses objektet for at være bevaret og logger dette som et potentielt hukommelseslækage i logcat’en. Ganske smart, ikke sandt?

For at komme i gang skal du blot tilføje biblioteket inden for dine afhængigheder til din build.gradle-fil, synkronisere og kompilere.

Føj LeakCanary-biblioteket til

Så snart du starter programmet, kan du se LeakCanary-udgangen i logcat’en, da den overvåger instants og beholder objekter. For at udløse en lækage tilføjede jeg et par nye opgaver i min TaskManager-app. Ikke længe efter fik jeg denne meddelelse fra LeakCanary, som indikerer en potentiel lækage!

Du skal blot klikke på meddelelsen for at “dump heap” for at undersøge den potentielle lækage, og denne dialogboks vil blive vist i appen.

LeakCanary undersøger lækagerne ..

Leak Canary analyserer derefter heap’en ved at lokalisere de tilbageholdte objekter og finder lækagesporet, som er en sti med referencer til hvert tilbageholdt objekt. Når det er gjort, vises en meddelelse, der opsummerer antallet af tilbageholdte objekter og lækager.

Det ser ud til, at den har fundet vores lækage! Hvis vi klikker på den, ser vi den fulde lækagesporing:

Den fortæller os, at TaskActivity lækker, og de understregede referencer viser sporet, at den lækker fra mContext i SingletonExample – lyder bekendt! Nu ved vi, hvordan vi kan finde en lækage ved hjælp af LeakCanary. 😃

Undgå hukommelseslækager

Så nu, hvor vi har fundet vores hukommelseslækage, hvordan kan vi så undgå dem i fremtiden? Nedenfor er nogle af de mest almindelige årsager og mønstre.

Foto af Bogomil Mihaylov på Unsplash

Broadcast-modtagere

Broadcast-modtagere kan bruges til at lytte til systemdækkende broadcast-hændelser eller hensigter, der angiver oplysninger om enheden, f.eks. lavt batteri, dato og ændringer i forbindelsesmuligheder – f.eks. at flytilstand er blevet slået fra. Når vi bruger dem, skal vi huske at afregistrere broadcast-modtagere, da vi ellers uundgåeligt vil beholde en reference til aktiviteten.

Sådan undgår du det: Det eneste du skal gøre er at kalde unregister() på din broadcast-modtager i onStop() i din aktivitet.

Dette mønster findes også for asyncTask, TimerTask og tråde, som skal annulleres i onDestroy() for at undgå en lækage.

Kontekst til Singleton-klasse

I nogle tilfælde har vi brug for at videregive kontekst fra en aktivitet til en Singleton-klasse. Et eksempel på dette ville være en utils-klasse, hvor vi har brug for at få adgang til ressourcer, tjenester eller interne filer. Overførsel af kontekst betyder imidlertid, at vi uundgåeligt holder fast i en reference til aktiviteten.

Sådan undgår du det: I stedet for at videregive this fra en aktivitet kan vi videregive applikationskontekst, hvis den er tilgængelig (hvis du vil lære mere om, hvornår du skal bruge hvilken kontekst, fandt jeg denne artikel meget nyttig!). En alternativ løsning er at sikre, at vi indstiller Singleton-konteksten til null inde i aktiviteten onDestroy()-metoden.

Statiske referencer

Referencer til en visning eller en aktivitet som statisk betyder, at referencen til aktiviteten ikke bliver skraldet. Dette bør simpelthen undgås til enhver tid.

Sådan undgår du det: Hvis du af en eller anden grund er nødt til at gøre det, kan du sikre, at den bliver destrueret ved at sætte den til null i onDestroy().

Innerklassereferencer

Innerklasser forårsager ofte lækager ved at holde en implicit reference til den ydre klasse. Dette sker, hvis klassevariablen er erklæret som statisk, eller hvis selve klassen ikke er erklæret som statisk. Forvirrende? Ja, men det er nemt at undgå, hvis vi følger den enkle regel nedenfor.

Sådan undgår du det: Gør den indre klasse statisk for at undgå at have en reference til den ydre klasse, og opret aldrig en statisk variabel for en indre klasse. Det samme gælder for anonyme klasser.

Det er det hele! Håber du har lært nogle ting om hukommelseslækager, og hvordan man undgår dem. God kodning! 😄

Her er en række artikler og dokumentation, som jeg fandt særligt nyttige, da jeg lærte om hukommelseslækager:

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.