自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

內(nèi)存泄露從入門到精通三部曲之常見原因與用戶實(shí)踐

移動(dòng)開發(fā)
一般我們所說的內(nèi)存泄漏有哪些原因,具體到用戶體驗(yàn)階段會(huì)有什么樣的問題?

常見原因

1.集合類

集合類如果僅僅有添加元素的方法,而沒有相應(yīng)的刪除機(jī)制,導(dǎo)致內(nèi)存被占用。如果這個(gè)集合類是全局性的變量 (比如類中的靜態(tài)屬性,全局性的 map 等即有靜態(tài)引用或 final 一直指向它),那么沒有相應(yīng)的刪除機(jī)制,很可能導(dǎo)致集合所占用的內(nèi)存只增不減。

2.單例模式

不正確使用單例模式是引起內(nèi)存泄露的一個(gè)常見問題,單例對(duì)象在被初始化后將在 JVM 的整個(gè)生命周期中存在(以靜態(tài)變量的方式),如果單例對(duì)象持有外部對(duì)象的引用,那么這個(gè)外部對(duì)象將不能被 JVM 正?;厥?,導(dǎo)致內(nèi)存泄露

3.Android組件或特殊集合對(duì)象的使用

BraodcastReceiver,ContentObserver,F(xiàn)ileObserver,Cursor,Callback等在 Activity onDestroy 或者某類生命周期結(jié)束之后一定要 unregister 或者 close 掉,否則這個(gè) Activity 類會(huì)被 system 強(qiáng)引用,不會(huì)被內(nèi)存回收。

不要直接對(duì) Activity 進(jìn)行直接引用作為成員變量,如果不得不這么做,請(qǐng)用 private WeakReference mActivity 來做,相同的,對(duì)于Service 等其他有自己聲明周期的對(duì)象來說,直接引用都需要謹(jǐn)慎考慮是否會(huì)存在內(nèi)存泄露的可能。

4. Handler

要知道,只要 Handler 發(fā)送的 Message 尚未被處理,則該 Message 及發(fā)送它的 Handler 對(duì)象將被線程 MessageQueue 一直持有。由于 Handler 屬于 TLS(Thread Local Storage) 變量, 生命周期和 Activity 是不一致的。因此這種實(shí)現(xiàn)方式一般很難保證跟 View 或者 Activity 的生命周期保持一致,故很容易導(dǎo)致無法正確釋放。如上所述,Handler 的使用要尤為小心,否則將很容易導(dǎo)致內(nèi)存泄露的發(fā)生。

5.Thread 內(nèi)存泄露

線程也是造成內(nèi)存泄露的一個(gè)重要的源頭。線程產(chǎn)生內(nèi)存泄露的主要原因在于線程生命周期的不可控。比如線程是 Activity 的內(nèi)部類,則線程對(duì)象中保存了 Activity 的一個(gè)引用,當(dāng)線程的 run 函數(shù)耗時(shí)較長(zhǎng)沒有結(jié)束時(shí),線程對(duì)象是不會(huì)被銷毀的,因此它所引用的老的 Activity 也不會(huì)被銷毀,因此就出現(xiàn)了內(nèi)存泄露的問題。

6.一些不良代碼造成的內(nèi)存壓力

有些代碼并不造成內(nèi)存泄露,但是它們,或是對(duì)沒使用的內(nèi)存沒進(jìn)行有效及時(shí)的釋放,或是沒有有效的利用已有的對(duì)象而是頻繁的申請(qǐng)新內(nèi)存。

6.1 Bitmap 沒調(diào)用 recycle(). Bitmap 對(duì)象在不使用時(shí),我們應(yīng)該先調(diào)用 recycle() 釋放內(nèi)存,然后才它設(shè)置為 null. 因?yàn)榧虞d Bitmap 對(duì)象的內(nèi)存空間,一部分是 java 的,一部分 C 的(因?yàn)?Bitmap 分配的底層是通過 JNI 調(diào)用的 )。 而這個(gè) recyle() 就是針對(duì) C 部分的內(nèi)存釋放。

6.2 構(gòu)造 Adapter 時(shí),沒有使用緩存的 convertView。


以業(yè)務(wù)測(cè)試過程中常見的部分內(nèi)存泄露實(shí)例來說明:

1. callback只有add操作,沒有注銷remove

 

從引用關(guān)系可以看到當(dāng)前 view 被 callback 引用,而 callback 被外部對(duì)象 sharkprotocolQueue 持有引用而導(dǎo)致泄漏。

2. 發(fā)送延時(shí)消息時(shí),如果該消息未處理,在退出頁面后會(huì)導(dǎo)致該頁面無法回收。

Android 應(yīng)用啟動(dòng)的時(shí)候會(huì)創(chuàng)建 UI 主線程的 Looper 對(duì)象,它存在于整個(gè)應(yīng)用的生命周期,用于處理消息隊(duì)列里的 Message。而這些 Message 會(huì)引用發(fā)送該消息的 Handler 對(duì)象。

那么問題來了,如果這些 Handler 是 Activity 的內(nèi)部類,那么當(dāng)這些 Handler 的消息未處理完或者消息本身是延時(shí)消息的話,就會(huì)導(dǎo)致 Activity 退出后,從 Activity 到 Handler 到 Message 到 Looper 的引用鏈條一直存在,從而導(dǎo)致 Activity 的泄露!

3. 異步線程未完成前退出 Activity 等組件,可能會(huì)導(dǎo)致界面資源無法釋放。

這種情況是典型的線程對(duì)象導(dǎo)致的內(nèi)存泄露。原因也很簡(jiǎn)單,線程 Thread 對(duì)象的 run 任務(wù)未執(zhí)行完之前,對(duì)象本身是不會(huì)釋放的。因此 Activity 等組件對(duì)象內(nèi)的線程對(duì)象成員如果有耗時(shí)任務(wù)(一般也都是耗時(shí)任務(wù)),就會(huì)導(dǎo)致一直持有組件本身的引用內(nèi)存泄露!

本文部分內(nèi)容和經(jīng)驗(yàn)摘自網(wǎng)絡(luò),結(jié)合本次內(nèi)存泄露的排查總結(jié)予以歸納。


優(yōu)秀實(shí)踐

  1. 對(duì)activity等組件的引用應(yīng)該控制在activity的生命周期之內(nèi); 如果不能就考慮使用 getApplicationContext或者getApplication,以避免activity被外部長(zhǎng)生命周期的對(duì)象引用而泄露

  2. 在代碼復(fù)審的時(shí)候關(guān)注長(zhǎng)生命周期對(duì)象:全局性的集合、單例模式的使用、類的static變量等等。

  3. 盡量不要在靜態(tài)變量或者靜態(tài)內(nèi)部類中使用非靜態(tài)外部成員變量(包括context),即使要使用,也要考慮適時(shí)把外部成員變量置空;也可以在內(nèi)部類中使用弱引用來引用外部類的變量;

  4. Handler的持有的引用對(duì)象***使用弱引用,資源釋放時(shí)也可以清空Handler里面的消息。比如在Activity onStop或者onDestroy的時(shí)候,取消掉該Handler對(duì)象的Message和Runnable:

  5. removeCallbacks(Runnable r)或removeMessages(int what),或removeCallbacksAndMessages(null)等。

  6. 線程Runnable執(zhí)行耗時(shí)操作,注意在頁面返回時(shí)及時(shí)取消或者把Runnable寫成靜態(tài)類。 a) 如果線程類是內(nèi)部類,改為靜態(tài)內(nèi)部類。 b) 線程內(nèi)如果需要引用外部類對(duì)象如context,需要使用弱引用。

  7. 在Java的實(shí)現(xiàn)過程中,也要考慮其對(duì)象釋放,***的方法是在不使用某對(duì)象時(shí),顯式地將此對(duì)象賦空,如清空對(duì)圖片等資源有直接引用或者間接引用的數(shù)組(使用array.clear();array = null),***遵循誰創(chuàng)建誰釋放的原則。


騰訊Bugly簡(jiǎn)介

Bugly是騰訊內(nèi)部產(chǎn)品質(zhì)量監(jiān)控平臺(tái)的外發(fā)版本,其主要功能是App發(fā)布以后,對(duì)用戶側(cè)發(fā)生的Crash以及卡頓現(xiàn)象進(jìn)行監(jiān)控并上報(bào),讓開發(fā)同學(xué)可以***時(shí)間了解到App的質(zhì)量情況,及時(shí)機(jī)型修改。目前騰訊內(nèi)部所有的產(chǎn)品,均在使用其進(jìn)行線上產(chǎn)品的崩潰監(jiān)控。

責(zé)任編輯:倪明 來源: 騰訊Bugly
相關(guān)推薦

2015-11-18 09:28:44

內(nèi)存泄露入門

2015-11-09 11:48:20

內(nèi)存泄漏基礎(chǔ)知識(shí)

2009-09-14 09:04:17

CCNA考試CCNA

2011-03-25 09:56:40

Nagios 安裝

2010-07-17 01:12:31

Telnet服務(wù)

2010-09-26 14:39:40

DHCP故障分析

2011-03-09 09:30:52

Mina

2011-03-28 16:52:08

用戶體驗(yàn)Android

2011-08-03 10:33:05

網(wǎng)絡(luò)管理網(wǎng)絡(luò)拓?fù)涔芾?/a>

2019-03-28 14:45:33

數(shù)據(jù)安全數(shù)據(jù)泄露信息安全

2022-10-10 09:10:51

家庭網(wǎng)絡(luò)網(wǎng)絡(luò)

2011-03-21 09:22:46

Tomcat

2013-06-28 09:35:04

Hypervisor虛擬化成本

2010-09-06 09:22:26

CSS語法

2012-09-10 16:19:00

云計(jì)算公共云

2015-05-12 10:42:53

程序員代碼

2017-02-07 14:50:39

華為

2017-04-11 09:07:20

互聯(lián)網(wǎng)

2011-08-29 16:26:50

魔獸世界LUA

2010-05-12 10:51:06

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)