Muistiprofiili on Android Profilerin komponentti, joka auttaa sinua tunnistamaan muistivuodot ja muistinvuodot, jotka voivat johtaa pysähtymiseen, jäätymiseen ja jopa sovelluksen kaatumiseen. Se näyttää reaaliaikaisen kuvaajan sovelluksen muistinkäytöstä, ja sen avulla voit kaapata kasan tyhjennyksen, pakottaa roskienkeräykset ja seurata muistin allokointeja.
Avataksesi muistiprofiilin noudata seuraavia ohjeita:
- Klikkaa Näkymä > Työkalunäkymä > Profiilinäkymä > (voit myös klikata Profiili-työkalurivillä).
- Valitse AndroidProfiler-työkaluriviltävalitäjälaite ja sovellusprosessi, jonka haluat profiloida. Jos olet liittänyt laitteen USB:n kautta, mutta et näe sitä listattuna, varmista, että olet ottanut USB-debuggauksen käyttöön.
- Klikkaa mitä tahansa MEMORY-aikataulussa avataksesi Memory Profilerin.
Vaihtoehtoisesti voit tarkastaa sovelluksen muistin komentoriviltä withdumpsys:llä ja nähdä GC-tapahtumat myös logcatissa.
Miksi sinun pitäisi profiloida sovelluksesi muisti
Android tarjoaa hallinnoidun muistiympäristön – kun se määrittelee, että sovelluksesi ei enää käytä joitain objekteja, roskienkerääjäpäästää käyttämättömän muistin takaisin kasaan. Sitä, miten Android etsii käyttämätöntä muistia, parannetaan jatkuvasti, mutta jossain vaiheessa kaikissa Androidversioissa järjestelmän on keskeytettävä koodisi hetkeksi. Useimmiten taukoja ei voi havaita. Jos sovelluksesi kuitenkin varaa muistia nopeammin kuin järjestelmä pystyy keräämään sitä, sovelluksesi saattaa viivästyä, kun keräilijä vapauttaa riittävästi muistia varattujen muistien täyttämiseksi. Viive voi aiheuttaa sovelluksessasi kehysten hyppäämistä ja näkyvää hitautta.
Jopa jos sovelluksessasi ei esiinny hitautta, jos se vuotaa muistia, se voi säilyttää sitä muistia myös taustalla ollessaan. Tämä käyttäytyminen voi hidastaa järjestelmän muun muistin suorituskykyä pakottamalla tarpeettomiin roskienkeräystapahtumiin. Lopulta järjestelmän on pakko tappaa sovellusprosessi saadakseen muistin takaisin. Sitten kun käyttäjä palaa sovellukseesi, se on käynnistettävä kokonaan uudelleen.
Välttääksesi näitä ongelmia sinun tulisi käyttää Memory Profileria seuraaviin toimiin:
- Etsiä epätoivottuja muistin allokaatiokuvioita aikajanalta, jotka saattavat aiheuttaa suorituskykyongelmia.
- Tyhjennä Javan kasa nähdäksesi, mitkä objektit käyttävät muistia kullakin tiettynä ajankohtana. Useat kasan tyhjennykset pidemmän ajanjakson aikana voivat auttaa tunnistamaanmuistivuodot.
- Tallenna muistin allokointi normaalin ja äärimmäisen käyttäjävuorovaikutuksen aikana, jotta voit tunnistaa tarkalleen, missä koodisi joko allokoi liikaa objekteja lyhyessä ajassa tai allokoi objekteja, jotka vuotavat.
Tietoa ohjelmointikäytännöistä, joilla voit vähentää sovelluksen muistinkäyttöä, saat lukemalla Sovelluksen muistin hallinta.
Muistiprofiilin yleiskatsaus
Kun avaat Muistiprofiilin ensimmäisen kerran, näet yksityiskohtaisen aikajanan sovelluksesi muistinkäytöstä ja pääset käsiksi työkaluihin, joilla voit pakottaa roskienkeräyksen (garbage collection), kaapata heapdumpin (heapdumppi) ja kirjata muistin allokaatioita.
>Kuva 1. Memory Profiler
Kuten kuvasta 1 käy ilmi, Memory Profilerin oletusnäkymä sisältää seuraavat:
- Painike roskienkeräystapahtuman pakottamiseen.
-
Painike kasan tyhjennyksen kaappaamiseen.
Huomautus: Painike muistin allokaatioiden tallentamiseen näkyy kasan tyhjennyspainikkeen oikealla puolella vain silloin, kun laite on liitetty laitteeseen, jossa on Android 7.1 (API-taso 25) tai alempi.
- Pudotusvalikko, jolla voidaan määrittää, kuinka usein profiloija tallentaa muistin allokaatiot. Sopivan vaihtoehdon valitseminen voi auttaa parantamaan sovelluksen suorituskykyä profiloinnin aikana.
- Painikkeet aikajanan suurentamiseen ja pienentämiseen.
- Painike, jolla voit hypätä eteenpäin live-muistitietoihin.
- Tapahtuma-aikajana, jossa näkyvät aktiviteettitilat, käyttäjän syöttötapahtumat ja näytön kiertotapahtumat.
- Muistinkäytön aikajana, joka sisältää seuraavat tiedot:
- Pinotettu kuvaaja siitä, kuinka paljon muistia kukin muistiluokka käyttää, kuten vasemmanpuoleinen y-akseli ja yläreunan väriavain osoittavat.
- Katkoviiva osoittaa allokoitujen objektien määrän, kuten oikeanpuoleinen y-akseli osoittaa.
- Symboli kutakin roskienkeräystapahtumaa varten.
Jos käytät laitetta, jossa käytetään Android 7.1:tä tai alempaa versiota, kaikki profiilitiedot eivät kuitenkaan ole oletusarvoisesti näkyvissä. Jos näet viestin ”Advancedprofiling is unavailable for the selected process” (Laajennettu profilointi ei ole käytettävissä valitun prosessin osalta), sinun on otettava käyttöön laajennettu profilointi nähdäksesi seuraavat tiedot:
- Tapahtuma-aikajana
- Varattujen objektien määrä
- Roskankeräystapahtumat
Android 8.0 ja uudemmat, kehittynyt profilointi on aina käytössä debuggattavissa sovelluksissa.
Miten muistia lasketaan
Muistiprofiilin yläreunassa näkyvät luvut (kuva 2) perustuvatkaikkiin yksityisiin muistisivuihin, jotka sovelluksesi on varannut, Android-järjestelmän mukaan. Tämä laskenta ei sisällä järjestelmän tai muiden sovellusten kanssa jaettuja sivuja.
Kuva 2. Memory Profilerin yläosassa oleva muistilaskennan legenda
Muistilaskennan luokat ovat seuraavat:
- Java: Java- tai Kotlin-koodista allokoitujen objektien muisti.
-
Native: Muisti objekteista, jotka on allokoitu C- tai C++-koodista.
Ja vaikka et käyttäisikään sovelluksessasi C++-koodia, saatat nähdä, että tässä käytetään jonkin verran natiivia muistia, koska Android-kehys käyttää natiivia muistia erilaisten tehtävien hoitamiseen puolestasi, esimerkiksi käsitellessäsi kuvavarantoja ja muita grafiikoita – vaikka kirjoittamasi koodi on Java- tai Kotlin-kielistä.
-
Grafiikka: Muisti, jota käytetään grafiikkapuskurijonoihin pikseleiden näyttämiseksi näytölle, mukaan lukien GL-pinnat, GL-tekstuurit ja niin edelleen. (Huomaa, että tämä on CPU:n kanssa jaettua muistia, ei omaa GPU-muistia.)
-
Stack: Sovelluksen sekä natiivien että Java-pinojen käyttämä muisti. Tämä liittyy yleensä siihen, kuinka monta säiettä sovelluksesi käyttää.
-
Code: Muisti, jota sovelluksesi käyttää koodiin ja resursseihin, kuten dex-bytekoodiin, optimoituun tai käännettyyn dex-koodiin, .so-kirjastoihin ja fontteihin.
-
Muut: Sovelluksesi käyttämä muisti, jota järjestelmä ei osaa luokitella.
-
Allocated: Sovelluksesi varaamien Java/Kotlin-objektien määrä. Tähän ei lasketa C- tai C++-kielellä allokoituja objekteja.
Kun olet yhteydessä laitteeseen, jossa on Android 7.1 tai uudempi, tämä allokointilaskenta alkaa vasta siitä hetkestä, kun Memory Profiler muodostaa yhteyden käynnissä olevaan sovellukseesi. Ennen profiloinnin aloittamista allokoituja objekteja ei siis oteta huomioon. Android 8.0 ja uudemmat versiot sisältävät kuitenkin laitteessa olevan profilointityökalun, joka seuraa kaikkia allokaatioita, joten tämä luku edustaa aina sovelluksessasi jäljellä olevien Java-objektien kokonaismäärää Android 8.0:ssa ja uudemmissa versioissa.
Vertailtaessa aiemmasta Android Monitor -työkalusta saatuihin muistilukumääriin uusiMuistiprofiilitarkkailijat kirjaavat muistisi eri tavalla, joten saattaa tuntua siltä, kuin muistin käyttösi olisikin nyt suurempi. Memory Profiler valvoo joitakin ylimääräisiä kategorioita, jotka lisäävät kokonaismäärää, mutta jos olet kiinnostunut vain Java-käyttömuistista, ”Java”-luvun pitäisi olla samanlainen kuin edellisen työkalun arvo.Vaikka Java-luku ei luultavasti täsmälleen vastaa sitä, mitä näit AndroidMonitorissa, uusi luku ottaa huomioon kaikki fyysiset muistisivut, jotka on varattu sovelluksesi Java-käyttömuistiin sen jälkeen, kun se haarautui Zygotesta. Joten tämäantaa tarkan esityksen siitä, kuinka paljon fyysistä muistia sovelluksesi todellisuudessa käyttää.
View memory allocations
Memory allocations näyttää, miten jokainen Java-objekti ja JNI-viittaus muistissasi on varattu. Tarkemmin sanottuna Memory Profiler voi näyttää objektien allokoinneista seuraavaa:
- Minkä tyyppisiä objekteja allokoitiin ja kuinka paljon tilaa ne käyttävät.
- Kunkin allokoinnin pinojälki, mukaan lukien missä säikeessä.
- Milloin objektit vapautettiin (vain käytettäessä laitetta, jossa on Android 8.0 tai uudempi).
Jos laitteessasi on Android 8.0 tai uudempi, voit tarkastella objektinallokaatioita milloin tahansa seuraavasti: Valitse aikajanalla vetämällä alue, jonka allokaatioita haluat tarkastella (kuten videossa 1 näkyy). Tallennusistuntoa ei tarvitse aloittaa, koska Android 8.0 ja uudempi sisältää laitteeseen kuulumattoman profilointityökalun, joka seuraa jatkuvasti sovelluksesi allokaatioita.
Video 1. Android 8.0:lla ja uudemmilla versioilla valitseolemassa oleva aikajanan alue tarkastellaaksesi kohteiden allokaatioita
Jos laitteessasi on Android 7.1 tai uudempi, napsauta Muistiprofiilityökalurivillä Tallenna muistinallokaatiot . Tallennuksen aikana Memory Profiler seuraa kaikkia sovelluksessa tapahtuvia allokaatioita. Kun olet valmis,napsauta Stop recording (sama painike; katso video 2) nähdäksesi allokaatiot.
Video 2. Android 7.1:ssä ja sitä uudemmissa versioissa sinun on tallennettava muistin allokaatiot
Kun valitset aikajanan alueen (tai kun lopetat tallennussession laitteella, jossa on Android 7.1 tai alempi), allokoitujenobjektien luettelo ilmestyy aikajanan alapuolelle ryhmiteltynä luokan nimen mukaan ja lajiteltuna niiden kasan lukumäärän mukaan.
Tarkastellaksesi allokointitallennetta noudata seuraavia vaiheita:
- Selaa luetteloa löytääksesi objekteja, joilla on epätavallisen suuret kasan lukumäärät jajotka saattavat olla vuotaneet. Tunnettujen luokkien löytämisen helpottamiseksi voit lajitella ne aakkosjärjestykseen napsauttamalla Luokan nimi -sarakkeen otsikkoa. Napsauta sitten luokan nimeä. Oikealle ilmestyy Instance View -ruutu, jossa näkyy jokainen kyseisen luokan instanssi, kuten kuvassa 3.
- Vaihtoehtoisesti voit etsiä objekteja nopeasti napsauttamalla Filter (Suodata) tai painamalla Control+F (Macissa Command+F) ja syöttämällä luokan tai pakkauksen nimen hakukenttään. Voit etsiä myös metodin nimen perusteella, jos valitset pudotusvalikostaArrange by callstack. Jos haluat käyttää säännönmukaisia lausekkeita, rastita Regex-kohdan vieressä oleva valintaruutu. Merkitse valintaruutu kohdanMatch case vieressä, jos hakukyselysi on suur- ja pienaakkoset huomioon ottava.
- Napsauta instanssinäkymäpaneelissa instanssia. Call Stack (Kutsupino) -välilehti avautuu alapuolelle ja näyttää, mistä kyseinen instanssi on varattu ja missä säikeessä.
- Call Stack (Kutsupino) -välilehdessä napsauta mitä tahansa riviä hiiren kakkospainikkeella ja valitseJumppaa lähdekoodiin avataksesi kyseisen koodin editoriin.
Kuva 3. Kutsupino -välilehti. Tiedot kustakin allokoidusta objektista näkyvät oikealla olevassa Instance-näkymässä
Voit käyttää allokoitujen objektien luettelon yläpuolella olevia kahta valikkoa valitaksesi, mikä kasa tarkastetaan ja miten tiedot järjestetään.
Vasemmalla olevasta valikosta voit valita, mikä kasa tarkastetaan:
- oletuskasa: Kun järjestelmä ei ole määrittänyt kasaa.
- kuvan kasa: Järjestelmän käynnistyskuva, joka sisältää luokat, jotka esiladataan käynnistyksen aikana. Allokaatiot täällä eivät taatusti koskaan siirry tai poistu.
- zygote heap: Copy-on-write heap, josta sovellusprosessi haarautuu Android-järjestelmässä.
- app heap: Ensisijainen heap, jossa sovellus varaa muistia.
- JNI heap: Kasa, josta näkyy, missä Java Native Interface (JNI)-viittaukset varataan ja vapautetaan.
Valitse oikealla olevasta valikosta, miten allokaatiot järjestetään:
- Järjestä luokittain: Ryhmittelee kaikki allokaatiot luokan nimen perusteella. Tämä on oletusarvo.
- Järjestä paketin mukaan: Ryhmittelee kaikki allokaatiot paketin nimen perusteella.
- Arrange by callstack: Ryhmittää kaikki allokaatiot vastaavaankutsupinoon.
Parantaa sovelluksen suorituskykyä profiloitaessa
Parantaaksesi sovelluksen suorituskykyä profiloitaessa, muistiprofiilintarkastaja ottaa oletusarvoisesti otoksia muistin allokaatioista säännöllisesti. Kun testaat laitteilla, joissa on APIlevel 26 tai uudempi, voit muuttaa tätä käyttäytymistä käyttämällä Allocation Tracking -pudotusvalikkoa. Käytettävissä olevat vaihtoehdot ovat seuraavat:
- Full (Täysi): Kaappaa kaikki muistissa olevat objektin allokaatiot. Tämä on oletuskäyttäytyminen Android Studio 3.2:ssa ja sitä aikaisemmissa versioissa. Jos sinulla on sovellus, joka allokoi paljon objekteja, saatat havaita näkyviä hidastuksia sovelluksessasi profiloinnin aikana.
- Sampled: Ottaa näytteitä objektien allokaatioista muistissa säännöllisin väliajoin. Tämä on oletusvaihtoehto, ja sillä on vähemmän vaikutusta sovelluksen suorituskykyyn profiloinnin aikana. Sovellukset, jotka allokoivat paljon objekteja lyhyessä ajassa, saattavat silti havaita näkyviä hidastumia.
- Off: Lopettaa sovelluksen muistin allokoinnin seurannan.
Katsele globaaleja JNI-viittauksia
Java Native Interface (JNI) on kehys, jonka avulla Java-koodi ja natiivikoodi voivat kutsua toisiaan.
Natiivikoodi hallinnoi JNI-viittauksia manuaalisesti, joten on mahdollista, että natiivikoodin käyttämiäJava-objekteja pidetään elossa liian kauan. Joitakin Javan kasassa olevia objekteja ei ehkä enää tavoiteta, jos JNI-viittaus hylätään ilman, että sitä on ensin nimenomaisesti poistettu. On myös mahdollista, että globaalien JNI-viittausten raja ylittyy.
Tällaisten ongelmien ratkaisemiseksi voit käyttää Memory Profilerin JNI heap -näkymää selataksesi kaikkia globaaleja JNI-viittauksia ja suodattaa ne Java-tyyppien ja natiivien kutsupinojen mukaan. Näiden tietojen avulla voit selvittää, milloin ja missä globaalit JNI-viittaukset luodaan ja poistetaan.
Valitse sovelluksen ollessa käynnissä aikajanan osa, jota haluat tarkastaa, ja valitse JNI heap luokkaluettelon yläpuolella olevasta pudotusvalikosta.Voit sitten tarkastaa kasassa olevia objekteja tavalliseen tapaan ja kaksoisnapsauttaaObjekteja Allocation Call Stack -välilehdellä nähdäksesi, missä JNI-viittaukset allokoidaan ja vapautetaan koodissasi, kuten kuvassa 4 näkyy.
Kuva 4. Globaalien JNI-viittausten tarkasteleminen
Tarkastellaksesi sovelluksesi JNI-koodin muistin allokaatioita, sinun on otettava sovellus käyttöön laitteeseen, jossa on Android 8.0 tai uudempi.
Lisätietoa JNI:stä on kohdassa JNI-vihjeitä.
Native Memory Profiler
Android Studio Memory Profiler sisältää Native Memory Profilerin sovelluksille, jotka on asennettu fyysisiin laitteisiin, joissa on Android 10; tuki Android 11-laitteille on tällä hetkellä saatavilla Android Studio 4.2:n esikatseluversiossa.
Native Memory Profiler seuraa natiivikoodin objektien allokaatioita/deallokaatioita tietyllä ajanjaksolla ja antaa seuraavat tiedot:
- Allokaatiot:
malloc()
– tainew
-operaattorin kautta allokoitujen objektien määrä valitun ajanjakson aikana. - Deallokointi:
free()
– taidelete
-operaattorin kautta poistettujen objektien määrä valitun ajanjakson aikana. - Allocations Size: Kaikkien allokaatioiden yhteenlaskettu koko tavuina valitun ajanjakson aikana.
- Deallocations Size: Kaikkien vapautetun muistin yhteenlaskettu koko tavuina valitun ajanjakson aikana.
- Total Count: Allocations-sarakkeen arvo miinus Deallocations-sarakkeen arvo.
- Jäljellä oleva koko: Allocations Size -sarakkeen arvo miinus Deallocations Size -sarakkeen arvo.
Tallennuksen aloittamiseksi napsauta Record native allocations (Tallenna natiivit allokaatiot) Muistiprofiileri-ikkunan yläreunassa:
Kun olet valmis lopettamaan tallennuksen, napsauta Stop recording (Pysäytä tallennus).
Oletusarvona Native Memory Profiler käyttää näytekokoa, jonka suuruusluokaksi on 32 tavua: Aina kun 32 tavua muistia varataan, muistista otetaan tilannekuva. Pienempi näytekoko johtaa tiheämpiin tilannekuviin, jolloin saadaan tarkempaa tietoa muistin käytöstä. Suurempi näytekoko tuottaa epätarkempia tietoja, mutta se kuluttaa vähemmän järjestelmän resursseja ja parantaa suorituskykyä tallennuksen aikana.
Muuttaa Native Memory Profilerin näytekokoa:
- Valitse Suorita > Muokkaa konfiguraatioita.
- Valitse sovelluksen moduuli vasemmasta ruudusta.
- Klikkaa Profilointi-välilehteä ja syötä näytekoko kenttään, jossa on merkintäNatiivimuistin näytteenottoväli (tavua).
- Rakenna ja suorita sovelluksesi uudelleen.
Kaappaa kasan dumppi
Kaapin dumppi näyttää, mitkä sovelluksen objektit käyttävät muistia silloin, kun kaappaat kasan dumppia. Etenkin pidemmän käyttäjäistunnon jälkeen heap dump voi auttaa tunnistamaan muistivuodot näyttämällä muistissa edelleen olevat objektit, joiden ei enää pitäisi olla siellä.
Kun otat heap dumpin, voit tarkastella seuraavia asioita:
- Minkä tyyppisiä objekteja sovelluksesi on varannut ja kuinka monta kutakin.
- Miten paljon muistia kukin objekti käyttää.
- Missä viittauksia kuhunkin objektiin pidetään koodissasi.
- Kutsupinon, jossa objekti on allokoitu. (Kutsupinot ovat tällä hetkellä käytettävissä kasan dumppauksen yhteydessä vain Android 7.1:ssä ja sitä uudemmissa versioissa, kun otat kasan dumppauksen taltioidessasi allokaatioita.)
Kaappaa kasan dumppaus napsauttamalla Muistiprofiili-työkalurivin Dump Java heap -painiketta.Kasan dumppauksen aikana Javan muistin määrä saattaa tilapäisesti kasvaa.Tämä on normaalia, koska kasan dumppaus tapahtuu samassa prosessissa kuin sovelluksesi ja vaatii jonkin verran muistia tietojen keräämiseen.
Kasan dumppaus näkyy muistin aikajanan alapuolella, ja siinä näkyvät kaikki kasassa olevat luokkatyypit, kuten kuvassa 5.
Kuva 5. Heap dumpin tarkastelu
Jos haluat tarkemmin tietää, milloin dump luodaan, voit luoda heap dumpin sovelluskoodin kriittisessä kohdassa kutsumalladumpHprofData()
.
Luokkien luettelossa näet seuraavat tiedot:
- Allocations: Allokaatioiden määrä kasassa.
-
Native Size: Tämän objektityypin käyttämän natiivimuistin kokonaismäärä (tavuina). Tämä sarake on näkyvissä vain Android 7.0:ssa ja uudemmissa versioissa.
Tässä näkyy joidenkin Javassa allokoitujen objektien muisti, koska Android käyttää natiivia muistia joillekin kehysluokille, kuten
Bitmap
. -
Natiivi koko: Tämän objektityypin käyttämän Java-muistin kokonaismäärä (tavuina).
-
Varattu koko: Kaikkien tämän luokan instanssien vuoksi säilytettävän muistin kokonaiskoko (tavuina).
Voit käyttää allokoitujen objektien luettelon yläpuolella olevia kahta valikkoa valitaksesi, mitkä heap-tyhjennykset tarkastetaan ja miten tiedot järjestetään.
Vasemmalla olevasta valikosta voit valita, mikä heap tarkastetaan:
- oletusheap: Kun järjestelmä ei ole määrittänyt kasaa.
- sovelluksen kasa: Ensisijainen kasa, johon sovelluksesi varaa muistia.
- image heap: Järjestelmän käynnistyskuva, joka sisältää luokat, jotka esiladataan käynnistyksen aikana. Allokaatiot täällä eivät taatusti koskaan siirry tai poistu.
- zygote heap: Copy-on-write-heap, josta sovellusprosessi haarautuu Android-järjestelmässä.
Valitse oikealla olevasta valikosta, miten allokaatiot järjestetään:
- Järjestä luokittain: Ryhmittelee kaikki allokaatiot luokan nimen perusteella. Tämä on oletusarvo.
- Järjestä paketin mukaan: Ryhmittelee kaikki allokaatiot paketin nimen perusteella.
- Arrange by callstack: Ryhmittelee kaikki allokaatiot vastaavaankutsupinoon. Tämä vaihtoehto toimii vain, jos kaappaat heap dumpin allokointeja tallentaessasi. Tällöinkin kasassa on todennäköisesti objekteja, jotka allokoitiin ennen tallentamisen aloittamista, joten nämä allokaatiot näkyvät ensimmäisenä,yksinkertaisesti listattuna luokan nimen mukaan.
Luettelo on oletusarvoisesti lajiteltu Retained Size -sarakkeen mukaan. Jos haluat lajitella jonkin muun sarakkeen arvojen mukaan, napsauta sarakkeen otsikkoa.
Klikkaa luokan nimeä avataksesi oikeanpuoleisen Instance View -ikkunan (kuvassa 6). Jokainen lueteltu instanssi sisältää seuraavat tiedot:
- Depth: Lyhin hyppyjen määrä mistä tahansa GC:n juuresta valittuun instanssiin.
- Native Size: Tämän instanssin koko natiivimuistissa.Tämä sarake näkyy vain Android 7.0:ssa ja uudemmissa versioissa.
- Shallow Size: Tämän instanssin koko Java-muistissa.
- Retained Size: Tämän instanssin hallitseman muistin koko (dominator-puun mukaan).
Kuvio 6. Muistin koko. Heapdumpin kaappaamiseen tarvittava kesto näkyy aikajanalla
Voit tarkastaa kasan noudattamalla seuraavia ohjeita:
- Selaa luetteloa etsiessäsi objekteja, joilla on epätavallisen suuri kasan määrä jajotka saattavat vuotaa. Tunnettujen luokkien löytämisen helpottamiseksi voit lajitella ne aakkosjärjestykseen napsauttamalla Luokan nimi -sarakkeen otsikkoa. Napsauta sitten luokan nimeä. Oikealle ilmestyy Instance View -ruutu, jossa näkyy jokainen kyseisen luokan instanssi, kuten kuvassa 6 on esitetty.
- Vaihtoehtoisesti voit etsiä objekteja nopeasti napsauttamalla Filter (Suodata) tai näppäilemällä Control+F (Macissa Command+F) ja kirjoittamalla luokan tai pakkauksen nimen hakukenttään. Voit hakea myös metodin nimen perusteella, jos valitset pudotusvalikostaArrange by callstack. Jos haluat käyttää säännönmukaisia lausekkeita, rastita Regex-kohdan vieressä oleva valintaruutu. Merkitse valintaruutu kohdanMatch case vieressä, jos hakukyselysi on suur- ja pienaakkoset huomioon ottava.
- Napsauta instanssinäkymäpaneelissa instanssia. Viittaustietokanta tulee näkyviin alapuolelle, jossa näkyvät kaikki viittaukset kyseiseen objektiin.
Vaihtaisitko napsauttamalla instanssin nimen vieressä olevaa nuolta nähdäksesi kaikki sen kentät ja napsauttamalla sitten kentän nimeä nähdäksesi kaikki sen viittaukset. Jos haluat tarkastella kentän instanssitietoja, napsauta kenttää hiiren kakkospainikkeella ja valitse Siirry instanssiin.
- Viittaukset-välilehdellä, jos tunnistat viittauksen, joka saattaa käyttää muistia, napsauta sitä hiiren kakkospainikkeella ja valitse Siirry instanssiin. Tämä valitsee vastaavan instanssin kasan tyhjennyksestä ja näyttää sen omat instanssitiedot.
Etsi kasan tyhjennyksestä muistivuodot, jotka johtuvat jostain seuraavista:
- Pitkäkestoiset viittaukset
Activity
-,Context
-,View
-,Drawable
– ja muihin objekteihin, jotka saattavat pitää sisällään viittauksenActivity
– taiContext
-säiliöön. - Epästaattiset sisäiset luokat, kuten
Runnable
, jotka voivat pitää hallussaanActivity
-instanssia. - Välimuistit, jotka pitävät objekteja hallussaan pidempään kuin on tarpeen.
Tallenna kasan tyhjennyskopio HPROF-tiedostona
Kun otat kasan tyhjennyskopion talteen, tiedot ovat katseltavissa Muistiprofiiliohjausohjelmassa vain profiilitarkkailijan ollessa käynnissä. Kun poistut profilointiistunnosta, menetät heap dumpin. Jos siis haluat tallentaa sen myöhempää tarkastelua varten, vie heap-dumppi HPROF-tiedostoon. Android Studio 3.1:ssä ja sitä uudemmissa versioissa Vie kaappaus tiedostoon -painike on työkalupalkin vasemmalla puolella aikajanan alapuolella; Android Studio 3.2:ssa ja sitä uudemmissa versioissa Export Heap Dump -painike on istuntoruudun jokaisen Heap Dump -merkinnän oikealla puolella. Tallenna tiedosto avautuvassa Export As -valintaikkunassa tiedostopäätteellä .hprof
.
Käyttääksesi erilaista HPROF-analysaattoria, kutenjhat,sinun on muunnettava HPROF-tiedosto Android-formaatista Java SE:n HPROF-formaattiin.Voit tehdä sen hprof-conv
-työkalulla, joka löytyy hakemistostaandroid_sdk/platform-tools/
. Suorita hprof-conv
komento kahdella argumentilla: alkuperäinen HPROF-tiedosto ja paikka, johon muunnettu HPROF-tiedosto kirjoitetaan. Esimerkiksi:
hprof-conv heap-original.hprof heap-converted.hprof
Import a heap dump file
Tuodaksesi HPROF-tiedoston (.hprof
), napsauta Start a new profiling session (Aloita uusi profilointiistunto) istuntoruudussa, valitse Load from file (Lataa tiedostosta) -valintaikkuna ja valitse tiedosto tiedostoselaimesta.
Voit tuoda HPROF-tiedoston myös raahaamalla sen tiedostoselaimesta editori-ikkunaan.
Vuotojen havaitseminen Memory Profilerissa
Analysoidessasi heap-dumppia Memory Profilerissa voit suodattaa profiilitietoja, jotka Android Studion mielestä saattavat viitata sovelluksen Activity
ja Fragment
instanssien muistivuotoihin.
Suodattimen näyttämiä tietotyyppejä ovat muun muassa seuraavat:
-
Activity
-instanssit, jotka on tuhottu mutta joihin edelleen viitataan. -
Fragment
-instanssit, joilla ei ole kelvollistaFragmentManager
:aa mutta joihin edelleen viitataan.
Tietyissä tilanteissa, kuten seuraavissa, suodatin saattaa tuottaa vääriä positiivisia tuloksia:
- A
Fragment
on luotu, mutta sitä ei ole vielä käytetty. - A
Fragment
on tallennettu välimuistiin, mutta se ei ole osaFragmentTransaction
:tä.
Käyttääksesi tätä ominaisuutta kaappaa ensin kasan tyhjennyskopiotai tuo kasan tyhjennyskopiotiedostoAndroid Studiossa. Jos haluat näyttää fragmentit ja aktiviteetit, jotka saattavat vuotaa muistia, valitse Activity/Fragment Leaks (Aktiviteetti-/fragmenttivuodot) -valintaruutu Memory Profilerin heapdump-ruudussa, kuten kuvassa 7 näkyy.
Kuva 7. Heapdumpin suodattaminen muistivuotojen varalta.
Tekniikoita muistin profilointiin
Muistiprofiilin käytön aikana kannattaa rasittaa sovelluskoodia ja kokeilla muistivuotojen etsimistä. Yksi tapa provosoida muistivuotoja sovelluksessasi on antaa sen toimia jonkin aikaa ennen kasan tarkastamista. Vuodot saattavat tihkua kasan allokointien yläpäähän. Mitä pienempi vuoto on, sitä pidempään sovellusta on kuitenkin pyöritettävä, jotta sen voi havaita.
Muistivuodon voi myös laukaista jollakin seuraavista tavoista:
- Laitteen kääntäminen muotokuvasta vaakakuvaan ja takaisin useita kertoja eri toimintatiloissa. Laitteen kääntäminen voi usein aiheuttaa sovellukselle vuodon
Activity
,Context
– taiView
-objektiin, koska järjestelmäluoActivity
:n ja jos sovelluksellasi on viittaus johonkin näistä objekteista jossain muualla, järjestelmä ei voi kerätä sitä roskakoriin. - Vaihda sovelluksesi ja toisen sovelluksen välillä, kun ne ovat eri toimintatiloissa (siirry kotinäyttöön ja palaa sitten takaisin sovellukseesi).
Vinkki: Voit suorittaa edellä mainitut vaiheet myös käyttämällä themonkeyrunner testframeworkia.