Android優(yōu)化-內(nèi)存優(yōu)化總結(jié)篇

一谬运、Android內(nèi)存管理機(jī)制

1、Java對(duì)象的生命周期

Java對(duì)象的生命周期經(jīng)歷7個(gè)階段垦藏,分別是創(chuàng)建階段梆暖、應(yīng)用階段、不可見(jiàn)階段掂骏、不可達(dá)階段轰驳、收集階段、終結(jié)階段、對(duì)象控件重新分配階段滑废。

2蝗肪、內(nèi)存回收機(jī)制

內(nèi)存的三個(gè)區(qū)域

內(nèi)存會(huì)有三個(gè)區(qū)域,Yong Generation(年輕代)蠕趁、Old Generation(年老代)薛闪、permanent Generation(持久代)。
其中年輕代里面又分為三個(gè)區(qū)俺陋,eden豁延、S0、S1腊状。

內(nèi)存的處理過(guò)程:

1.對(duì)象創(chuàng)建后在Eden區(qū)域诱咏,

2.執(zhí)行GC時(shí),如果對(duì)象仍然存貨缴挖,則復(fù)制到S0區(qū)袋狞。

3.當(dāng)S0區(qū)滿(mǎn)時(shí),改區(qū)域存活對(duì)象將復(fù)制到S1區(qū)映屋,然后S0清空苟鸯,接下來(lái)S0和S1角色互換。

4.當(dāng)?shù)谌窟_(dá)到一定次數(shù)后棚点,存活對(duì)象將被復(fù)制到Old Generation早处。

5.當(dāng)這個(gè)對(duì)象在Old Generation區(qū)域挺溜的時(shí)間達(dá)到一定程度時(shí),它會(huì)被移動(dòng)到Old Generation瘫析,最后積累一定時(shí)間再移動(dòng)到Permaent Generation區(qū)域砌梆,Permaent Generation區(qū)域也存放一些靜態(tài)文件。

GC回收的一些算法

Copying算法:掃描出存活的對(duì)象贬循,并復(fù)制到一塊新的完全未使用的控件中咸包,對(duì)應(yīng)于Young Generation,就是在Eden甘有、FromSpace或ToSpace之間copy诉儒。

標(biāo)記算法:掃描出存活對(duì)象,然后再回收未標(biāo)記的對(duì)象亏掀,回收后對(duì)空出的空間要么合并,要么標(biāo)記出來(lái)便于下次分配泛释,以減少內(nèi)存碎片帶來(lái)的損耗滤愕。年老代對(duì)象存活時(shí)間較長(zhǎng)較穩(wěn)定,使用標(biāo)記算法回收怜校。

GC類(lèi)型

1.kGcCauseForAlloc:在分配內(nèi)存時(shí)內(nèi)存不夠情況下引起的GC,這種情況下GC會(huì)stop World间影。Stop World 是由于并發(fā)GC時(shí),其他線(xiàn)程都會(huì)停止茄茁。

2.kGcCauseBackground:當(dāng)內(nèi)存達(dá)到一定閾值的時(shí)候引發(fā)GC魂贬,這個(gè)時(shí)候是一個(gè)后臺(tái)GC,不會(huì)引起Stop World巩割。

3.kGcCauseExplicit:顯示調(diào)用時(shí)進(jìn)行的GC,如果ART打開(kāi)了這個(gè)選項(xiàng)付燥,在system.gc時(shí)會(huì)進(jìn)行GC宣谈。

其他GC注意事項(xiàng)

1.盡量不去顯式調(diào)用 system.gc() 減少不必要的系統(tǒng)開(kāi)銷(xiāo),影響應(yīng)用的流暢度键科。

2.盡量減少內(nèi)存泄露闻丑,避免OOM。

二勋颖、Android內(nèi)存泄露

1嗦嗡、什么是內(nèi)存泄露?

java對(duì)象有自己的生命周期饭玲,當(dāng)這個(gè)對(duì)象不需要再使用時(shí)侥祭,應(yīng)該完整地走完生命周期,但因?yàn)槟承┰蚯牙澹瑢?duì)象雖然已經(jīng)不再使用卑硫,仍然在內(nèi)存中并沒(méi)有結(jié)束整個(gè)生命周期,這就意味著這個(gè)對(duì)象已經(jīng)泄露了蚕断。

GC會(huì)選擇一些還存活的對(duì)象作為內(nèi)存遍歷的根節(jié)點(diǎn) GC Roots,通過(guò)對(duì)GC Roots的可達(dá)性來(lái)判斷是否需要回收欢伏。


Android系統(tǒng)虛擬機(jī)的垃圾回收是通過(guò)虛擬機(jī)GC機(jī)制來(lái)實(shí)現(xiàn)的。GC會(huì)選擇一些存活的對(duì)象作為內(nèi)存便利的跟節(jié)點(diǎn)GC Roots,通過(guò)判斷GC Roots的可達(dá)性來(lái)判斷是否需要回收亿乳,如上圖其中 1 2 3 4直接或間接被GC Roots引用鏈相連硝拧,這類(lèi)對(duì)象被認(rèn)為還需要使用的對(duì)象,就不會(huì)被回收葛假。5 6 7將會(huì)被回收障陶。到那時(shí)這里如果Object4 如果不需要使用的話(huà)這時(shí)候也不會(huì)被回收,就屬于內(nèi)存泄露聊训。

2抱究、常見(jiàn)內(nèi)存泄露場(chǎng)景以及注意事項(xiàng)

~ 資源型對(duì)象未關(guān)閉
~ 注冊(cè)對(duì)象未注銷(xiāo)
~ 類(lèi)的靜態(tài)變量持有大數(shù)據(jù)對(duì)象 如bitmap
~ 費(fèi)靜態(tài)內(nèi)部類(lèi)的靜態(tài)實(shí)例
~ Handler臨時(shí)性?xún)?nèi)存泄露
~ 容器中的對(duì)象沒(méi)有清理造成的內(nèi)存泄露

3、內(nèi)存泄露分析工具

leakcanary

三带斑、常見(jiàn)注意事項(xiàng)避免內(nèi)存消耗過(guò)多

1鼓寺、AutoBoxing自動(dòng)裝箱過(guò)程

 Integer num=0;   
 for(int i=0;i<100;i++){
     num+=i;
??}??

這段代碼每次循環(huán),虛擬機(jī)都必須創(chuàng)建一個(gè)新的整數(shù)對(duì)象勋磕,并把它加到其他整數(shù)對(duì)象前面妈候,創(chuàng)建一個(gè)新的整數(shù)對(duì)象,意味著要消耗更多性能挂滓。int只有4字節(jié)苦银,而Integer對(duì)象有16字節(jié)。

2、內(nèi)容復(fù)用

1幔虏、有效利用系統(tǒng)自帶資源纺念。
2、視圖復(fù)用想括,如ViewHolder陷谱。
3、對(duì)象池主胧。
4叭首、Bitmap對(duì)象復(fù)用。

3踪栋、使用最優(yōu)的數(shù)據(jù)類(lèi)型

1焙格、當(dāng)對(duì)象的數(shù)目在1000以?xún)?nèi)且特別多訪(fǎng)問(wèn)而刪除和插入不高的時(shí)候盡量用ArrayMap替代HashMap。
2夷都、枚舉的最大優(yōu)點(diǎn)是安全眷唉、易讀,但是內(nèi)存消耗是定義常量的三倍以上囤官《簦可以使用注解方式來(lái)檢查安全。
3党饮、使用IntDef和StringDef檢查類(lèi)型安全肝陪。
4、LruCache建議使用這個(gè)緩存機(jī)制刑顺,但是既不能分配太大氯窍,也不能分配太小。

4蹲堂、圖片的內(nèi)存優(yōu)化

設(shè)置位圖規(guī)格狼讨,使用inSampleSize實(shí)現(xiàn)位圖縮放和壓縮。使用緩存機(jī)制等柒竞。

四政供、內(nèi)存分析工具

1、Memory Monitor

這個(gè)是一個(gè)我們開(kāi)發(fā)過(guò)程中很常用的內(nèi)存朽基、CPU布隔、網(wǎng)絡(luò)的分析工具。


Memory Monitor界面視圖

界面很直觀(guān)踩晶,左上角有運(yùn)行的機(jī)型和項(xiàng)目包名执泰,然后最直觀(guān)的動(dòng)態(tài)圖,分別是CPU渡蜻、Memory、NetWork。點(diǎn)進(jìn)去可以進(jìn)入的Memory茸苇。


Memory Monitor的Memory局部視圖

這里可以清晰的看到顏色對(duì)應(yīng)區(qū)域占用的內(nèi)存大小排苍。
Memory Monitor的Memory整體視圖

通過(guò)這兩張圖 內(nèi)存的大部分信息都能查閱到。我們?cè)诓僮鰽PP加載圖片等操作時(shí)候能看到內(nèi)存上升学密、和下降淘衙,如果操作APP后發(fā)現(xiàn)內(nèi)存不會(huì)下降可能就是我們有些對(duì)象沒(méi)有及時(shí)釋放,也有可能導(dǎo)致內(nèi)存泄露腻暮。
還有對(duì)應(yīng)的模擬GC彤守,查看時(shí)間段具體內(nèi)存信息以及一段時(shí)間的內(nèi)存追蹤等工具可以使用】蘧福可以定位到具體的代碼行具垫。如下圖:


具體類(lèi)詳細(xì)內(nèi)存信息展示

這里有一個(gè)Shallow size這個(gè)屬性的概念:
Shallow size就是對(duì)象本身占用內(nèi)存的大小,不包含其引用的對(duì)象试幽。常規(guī)對(duì)象(非數(shù)組)的Shallow size有其成員變量的數(shù)量和類(lèi)型決定筝蚕。數(shù)組的shallow size有數(shù)組元素的類(lèi)型(對(duì)象類(lèi)型、基本類(lèi)型)和數(shù)組長(zhǎng)度決定铺坞。

2起宽、Heap Viewrer

Heap Viewrer工具視圖界面

如果是Android Studio的話(huà)通過(guò)Tools->Android->Android Device Monitor找到這個(gè)工具。
進(jìn)入后選擇運(yùn)行APP的包名然后點(diǎn)擊update Heap按鈕济榨,這時(shí)候會(huì)在每次gc時(shí)展示數(shù)據(jù)信息坯沪,也可以在后面手動(dòng)GC,如果在操作頁(yè)面這時(shí)候可能會(huì)發(fā)現(xiàn)小卡頓擒滑,因?yàn)樵贕C時(shí)腐晾,可能導(dǎo)致其他線(xiàn)程停止工作,這時(shí)可以清晰看到表中內(nèi)存信息:
頭部總覽視圖:

標(biāo)題 含義
Heap Size 堆棧分配給APP的內(nèi)存大小橘忱。
Allocated 已分配使用的內(nèi)存大小赴魁。
Free 空閑的內(nèi)存大小。
%Used Allocated/Heap Size 的使用率钝诚。
#Object 對(duì)象數(shù)量

下面詳情視圖:

標(biāo)題 含義
free 空閑的對(duì)象
data object 數(shù)據(jù)對(duì)象颖御,Java類(lèi)類(lèi)型對(duì)象,是最主要的觀(guān)察對(duì)象凝颇。
class object java類(lèi)類(lèi)型的引用對(duì)象潘拱。
1-byte array(byte[],boolean[]) 一字節(jié)的數(shù)組對(duì)象。
2-byte array(short[],char[]) 兩字節(jié)的數(shù)組對(duì)象拧略。
4-byte array(object[],int[],float[]) 4字節(jié)的數(shù)組對(duì)象芦岂。
8-byte array(long[],double[]) 8字節(jié)的數(shù)組對(duì)象。
non-java object 非Java對(duì)象垫蛆。

每個(gè)類(lèi)型的數(shù)據(jù)值對(duì)應(yīng):

標(biāo)題 含義
Count 數(shù)量
Total Size 總共占用的內(nèi)存的大小
Smallest 將對(duì)象占用內(nèi)存從小到大排列禽最,排在第一個(gè)對(duì)象占用內(nèi)存大小
Largest 將對(duì)象占用內(nèi)存從小到大排列腺怯,排在最后一個(gè)對(duì)象占用的內(nèi)存大小。
Median 將對(duì)象占用內(nèi)存從小到大排列川无,排在總監(jiān)的對(duì)象占用的內(nèi)存大小呛占。
Average 平均值
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市懦趋,隨后出現(xiàn)的幾起案子晾虑,更是在濱河造成了極大的恐慌,老刑警劉巖仅叫,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帜篇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡诫咱,警方通過(guò)查閱死者的電腦和手機(jī)笙隙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)遂跟,“玉大人逃沿,你說(shuō)我怎么就攤上這事』盟” “怎么了凯亮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)哄尔。 經(jīng)常有香客問(wèn)我假消,道長(zhǎng),這世上最難降的妖魔是什么岭接? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任富拗,我火速辦了婚禮,結(jié)果婚禮上鸣戴,老公的妹妹穿的比我還像新娘啃沪。我一直安慰自己,他們只是感情好窄锅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布创千。 她就那樣靜靜地躺著,像睡著了一般入偷。 火紅的嫁衣襯著肌膚如雪追驴。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天疏之,我揣著相機(jī)與錄音殿雪,去河邊找鬼。 笑死锋爪,一個(gè)胖子當(dāng)著我的面吹牛丙曙,可吹牛的內(nèi)容都是我干的爸业。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼河泳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沃呢!你這毒婦竟也來(lái)了年栓?” 一聲冷哼從身側(cè)響起拆挥,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎某抓,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡塔鳍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年愕乎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片备禀。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洲拇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出曲尸,到底是詐尸還是另有隱情赋续,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布另患,位于F島的核電站纽乱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏昆箕。R本人自食惡果不足惜鸦列,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹏倘。 院中可真熱鬧薯嗤,春花似錦、人聲如沸纤泵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夕吻。三九已至诲锹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涉馅,已是汗流浹背归园。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稚矿,地道東北人庸诱。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓捻浦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親桥爽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子朱灿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容