Android L,gc android,Android GC Log解讀

 2023-11-19 阅读 24 评论 0

摘要:寫在前面英文原版鏈接,若是覺得本文哪里不好還請指出,以便及時修改,以下是譯文安卓是為移動設備設計的,所以開發者應該時刻留意app占用的RAM(Random-Access Memory)。盡管Dalvik和ART會例行垃圾回收(GC),但并不代表開發者可以忽略app的內存

寫在前面

英文原版鏈接,若是覺得本文哪里不好還請指出,以便及時修改,以下是譯文

安卓是為移動設備設計的,所以開發者應該時刻留意app占用的RAM(Random-Access Memory)。盡管Dalvik和ART會例行垃圾回收(GC),但并不代表開發者可以忽略app的內存使用情況(什么時候在哪里分配/釋放了多少內存)。為了確保穩定的用戶體驗,讓系統能夠在多個app之間迅速切換,app不要在用戶沒有和它交互時消耗不必要的內存,這一點很重要

P.S.Dalvik(Android專用的JVM)、ART(Android Runtime),Android4.4引入了ART,之前是Dalvik

Android L,即便在開發期間遵循所有的最佳實踐來管理app的內存(開發者理應這樣做),也可能會出現對象泄漏或者其它內存bug。唯一可靠的,能盡量減少app內存占用的方法就是用工具分析app的內存使用情況,本篇指南將詳細說明應該怎么做

Log信息解釋

查看app內存使用情況最簡單的方式是運行時的log信息,GC執行后,會輸出一段信息到logcat。logcat的輸出可以在Device Monitor里查看,或者直接在IDE比如Android Studio里查看

Dalvik Log信息

在Dalvik(不是ART)模式下,每次FC會在logcat輸出如下信息:

android:label、D/dalvikvm: , , ,

例如:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms

GC Reason

什么觸發了GC,以及屬于哪種類型的垃圾回收,可能出現的值包括:

Android Q,GC_CONCURRENT

heap快滿了引起的并發GC

GC_FOR_MALLOC

heap已經滿了,此時app嘗試分配內存,所以系統只好阻止app并回收內存,導致內存分配失敗

GC_HPROF_DUMP_HEAP

android打開開發者模式、請求創建一個用來分析heap的HPROF文件,引發GC

P.S.hprof文件描述了heap使用情況,類似于Chrome的heapsnapshot文件

GC_EXPLICIT

顯式GC,例如調用gc()(這種方式應該避免,要相信GC會在需要的時候自動執行)

GC_EXTERNAL_ALLOC

外部內存分配(比如像素數據存儲在native memory里或者NIO byte buffer)引起的GC,只會在API 10和更低版本中出現(新一點的版本所有東西都在Dalvik heap里分配)

Amount freed

本次GC回收的內存大小

Heap stats

heap中可用內存所占百分比,以及[已使用內存大小]/[heap總大小]

External memory stats

外部內存統計數據,

在API 10和更低版本中,外部分配的內存,以及[已分配內存大小]/[GC下限]

P.S.達到GC下限時進行GC

Pause time

heap越大,需要的停頓次數越多,并發GC(GC Reason為GC_CONCURRENT)的停頓次數分2部分:第一部分是GC開始時,另一部分是GC結束時

記下這些log信息,關注heap stats(例子中是3571K/9991K),如果持續增長,可能就存在內存泄漏了

ART Log信息

與Dalvik不同,ART不會log非顯式(隱式)請求的GC,GC只會在被判定為很慢時輸出信息。更準確地,條件是GC停頓超過5ms,或者GC耗時超過100ms。如果app不是處于一種可察覺的停頓狀態,那么GC不會就被判定為很慢,而顯式GC會被log出來

ART的GC log中包含了以下信息:

I/art: () AllocSpace Objects, () LOS objects,

例如:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms

GC Reason

什么觸發了GC,以及屬于哪種類型的垃圾回收,可能出現的值包括:

Concurrent

并發GC,不會掛起app線程,這種GC在后臺線程中運行,不會阻止內存分配

Alloc

GC被初始化,app在heap已滿的時候請求分配內存,此時,GC會在當前線程(請求分配內存的線程)執行

Explicit

GC被app顯式請求,例如,通過調用System.gc()或者runtime.gc()。和Dalvik一樣,ART建議相信GC,盡可能地避免請求顯式GC。不建議使用顯式GC,因為會阻塞當前線程,并引起不必要的CPU周期。如果GC導致其它線程被搶占的話,顯式GC還會引發jank

P.S.jank是指第n幀繪制過后,本該繪制第n+1幀,但因為CPU被搶占,數據沒有準備好,只好再顯示一次第n幀,下一次繪制時顯示第n+1幀

NativeAlloc

來自native分配的native memory壓力引起的GC,比如Bitmap或者RenderScript對象

CollectorTransition

heap變遷引起的GC,運行時動態切換GC造成的,垃圾回收器變遷過程包括從free-list backed space復制所有對象到bump pointer space(反之亦然)。當前垃圾回收器過渡只會在低RAM設備的app改變運行狀態時發生,比如從可察覺的停頓態到非可察覺的停頓態(反之亦然)

HomogeneousSpaceCompact

Homogeneous space compaction是free-list space與free-list space的合并,經常在app變成不可察覺的停頓態時發生,這樣做的主要原因是減少RAM占用并整理heap碎片

DisableMovingGc

不是一個真正的GC原因,正在整理碎片的GC被GetPrimitiveArrayCritical阻塞,一般來說,因為GetPrimitiveArrayCritical會限制垃圾回收器過渡,強烈建議不要使用

HeapTrim

不是一個真正的GC原因,但GC被阻塞,直到heap trim結束

GC Name

ART有幾種不同的GC

Concurrent mark sweep (CMS)

全堆垃圾收集器,負責收集釋放除image外的所有空間

Concurrent partial mark sweep

差不多是全堆垃圾收集器,負責收集除image和zygote外的所有空間

Concurrent sticky mark sweep

分代垃圾收集器,只負責釋放從上次GC到現在分配的對象,該GC比全堆和部分標記清除(mark sweep)執行得更頻繁,因為它更快而且停頓更短

Marksweep + semispace

非并發的,復制堆過渡和homogeneous space compaction(用來整理heap碎片)使用的GC

Objects freed

本次GC從非大對象空間(non large object space)回收的對象數目

Size freed

本次GC從非大對象空間回收的字節數

Large objects freed

本次GC從大對象空間里回收的對象數目

Large object size freed

本次GC從大對象空間里回收的字節數

Heap stats

可用空間所占的百分比和[已使用內存大小]/[heap總大小]

Pause times

一般情況下,GC運行時,停頓次數和被修改的對象引用數成比例。目前,ART CMS GC只會在GC結束的時停頓一次,GC過渡會有一個長停頓,是GC時耗的主要因素

如果在logcat看到一堆GC信息,找到heap stats(例子中是25MB/38MB),如果持續增長從不減小,就可能存在內存泄漏。如果看到GC的原因是Alloc,那么說明heap已經要滿了,快OOM了

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/182277.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息