Android中的內(nèi)存泄漏


Android中的內(nèi)存泄漏:

概念:程序在申請內(nèi)存后商蕴,當(dāng)該內(nèi)存不需再使用但卻無法被釋放 & 歸還給程序的現(xiàn)象励烦,對應(yīng)用程序的影響贝或,容易使得應(yīng)用程序發(fā)生內(nèi)存溢出吼过,即?OOM锐秦,其實(shí)也就是當(dāng)一個對象使用完畢后,被另外一個對象持有并引用盗忱,導(dǎo)致無法被回收的現(xiàn)象叫內(nèi)存泄漏酱床。

內(nèi)存泄露的危害

  內(nèi)存泄露的危害就是會使虛擬機(jī)占用內(nèi)存過高,導(dǎo)致OOM(內(nèi)存溢出)趟佃,程序出錯扇谣。

  對于Android應(yīng)用來說,就是你的用戶打開一個Activity闲昭,使用完之后關(guān)閉它罐寨,內(nèi)存泄露;又打開汤纸,又關(guān)閉衩茸,又泄露;幾次之后贮泞,程序占用內(nèi)存超過系統(tǒng)限制,F(xiàn)C幔烛。

導(dǎo)致內(nèi)存泄漏的情況:可以說啃擦,書寫代碼的過程中任何情況都會出現(xiàn)內(nèi)存泄漏。但饿悬,總體來分析的話,有以下幾個原因:

一:線程導(dǎo)致的內(nèi)存泄漏:在Activity 銷毀之前令蛉,線程的任務(wù)并沒有執(zhí)行完畢,就會導(dǎo)致內(nèi)存泄漏狡恬。

解決辦法:將AsyncTask和Runnable類獨(dú)立出來或者使用靜態(tài)內(nèi)部類珠叔,這樣便可以避免內(nèi)存泄漏。

舉例:
public class MainActivity extends AppCompatActivity {

? ? @Override

? ? protected void onCreate(Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? new Thread(new MyRunnable()).start();

? ? ? ? new MyAsyncTask(this).execute();

? ? }

? ? class MyAsyncTask extends AsyncTask<Void, Void, Void> {

? ? ? ? // ...

? ? ? ? public MyAsyncTask(Context context) {

? ? ? ? ? ? // ...

? ? ? ? }

? ? ? ? @Override

? ? ? ? protected Void doInBackground(Void... params) {

? ? ? ? ? ? // ...

? ? ? ? ? ? return null;

? ? ? ? }

? ? ? ? @Override

? ? ? ? protected void onPostExecute(Void aVoid) {

? ? ? ? ? ? // ...

? ? ? ? }

? ? }

? ? class MyRunnable implements Runnable {

? ? ? ? @Override

? ? ? ? public void run() {

? ? ? ? ? ? // ...

? ? ? ? }

? ? }

}

二 :單例模式導(dǎo)致的內(nèi)存泄漏:因?yàn)閱卫撵o態(tài)屬性使得生命周期和應(yīng)用程序的生命周期一樣長弟劲。若1個對象已不需再使用而單例對象還持有該對象的引用祷安,那么該對象將不能被正常回收從而 導(dǎo)致內(nèi)存泄漏兔乞。

解決辦法:使用Appaction中context上下文汇鞭,因?yàn)檫@樣不管傳入什么Context最終將使用Application的Context,而單例的生命周期和應(yīng)用的一樣長庸追,這樣就防止了內(nèi)存泄漏霍骄。

// 使用了單例模式舉例:

public class AppManager {

? ? private static AppManager instance;

? ? private Context context;

? ? private AppManager(Context context) {

? ? ? ? this.context = context;

? ? }

? ? public static AppManager getInstance(Context context) {

? ? ? ? if (instance != null) {

? ? ? ? ? ? instance = new AppManager(context);

? ? ? ? }

? ? ? ? return instance;

? ? }

};

三:Handler造成的內(nèi)存泄漏:Handler是處理進(jìn)程間通信的機(jī)制淡溯,那么读整,當(dāng)MainActivity結(jié)束時,未處理的消息持有handler的引用咱娶,而handler又持有它所屬的外部類也就是MainActivity的引用米间。這條引用關(guān)系會一直保持直到消息得到處理煎楣,這樣阻止了MainActivity被垃圾回收器回收,從而造成了內(nèi)存泄漏车伞。

解決辦法:1:將Handler獨(dú)立出來择懂。2:將Handler聲明為靜態(tài)類 。3:在關(guān)閉Activity的時候停掉你的后臺線程另玖。線程停掉了困曙,就相當(dāng)于切斷了Handler和外部連接的線,Activity自然會在合適的時候被回收谦去。

舉例:注意這個時候Handler中增加了一個對Activity的弱引用(WeakReference)慷丽。

static class MyHandler extends Handler

? ? {

? ? ? ? WeakReference<Activity> mWeakReference;

? ? ? ? public MyHandler(Activity activity)

? ? ? ? {

? ? ? ? ? ? mWeakReference=new WeakReference<Activity>(activity);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void handleMessage(Message msg)

? ? ? ? {

? ? ? ? ? ? final Activity activity=mWeakReference.get();

? ? ? ? ? ? if(activity!=null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? if (msg.what == 1)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? noteBookAdapter.notifyDataSetChanged();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

四:使用資源導(dǎo)致的內(nèi)存泄漏: 對于資源的使用(如 廣播BraodcastReceiver、文件流File鳄哭、數(shù)據(jù)庫游標(biāo)Cursor要糊、圖片資源Bitmap等),若在Activity銷毀時無及時關(guān)閉 / 注銷這些資源妆丘,則這些資源將不會被回收锄俄,從而造成內(nèi)存泄漏。

解決辦法:資源使用完畢后勺拣,(Activity銷毀)一定要及時關(guān)閉/銷毀資源奶赠。

五:集合類使用導(dǎo)致的內(nèi)存泄漏:集合容器中的內(nèi)存泄露 我們通常把一些對象的引用加入到了集合容器(比如ArrayList)中,當(dāng)我們不需要該對象時药有,并沒有把它的引用從集合中清理掉毅戈,這樣這個集合就會越來越大。導(dǎo)致內(nèi)存泄漏愤惰,甚至于程序崩潰苇经。

解決方法:在退出程序之前,或使用完集合時宦言,將集合里的東西clear扇单,然后置為null,再退出程序蜡励。

六:webView造成的內(nèi)存泄漏:當(dāng)我們不要使用WebView對象時令花,應(yīng)該調(diào)用它的destory()函數(shù)來銷毀它,并釋放其占用的內(nèi)存凉倚,否則其長期占用的內(nèi)存也不能被回收兼都,從而造成內(nèi)存泄露。

解決辦法:不再需要使用WebView時稽寒,及時使用destory銷毀它扮碧。

七:.Static關(guān)鍵字修飾的成員變量導(dǎo)致的內(nèi)存泄漏:若使被 Static 關(guān)鍵字修飾的成員變量 引用耗費(fèi)資源過多的實(shí)例(如Context),則容易出現(xiàn)該成員變量的生命周期 > 引用實(shí)例生命周期的情況,當(dāng)引用實(shí)例需結(jié)束生命周期銷毀時慎王,會因靜態(tài)變量的持有而無法被回收蚓土,從而出現(xiàn)內(nèi)存泄露。

解決辦法:盡量避免?Static?成員變量引用資源耗費(fèi)過多的實(shí)例赖淤。

如何檢測內(nèi)存泄漏 蜀漆,如何優(yōu)化內(nèi)存泄漏:

MAT(Memory Analysis Tools)

Heap Viewer

Allocation Tracker

Android Studio 的 Memory Monitor LeakCanary


參考來源:http://www.reibang.com/p/90caf813682d 來源:簡書 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)咱旱,非商業(yè)轉(zhuǎn)載請注明出處确丢。




?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吐限,隨后出現(xiàn)的幾起案子鲜侥,更是在濱河造成了極大的恐慌,老刑警劉巖诸典,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件描函,死亡現(xiàn)場離奇詭異,居然都是意外死亡狐粱,警方通過查閱死者的電腦和手機(jī)舀寓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脑奠,“玉大人基公,你說我怎么就攤上這事∷纹郏” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵胰伍,是天一觀的道長齿诞。 經(jīng)常有香客問我,道長骂租,這世上最難降的妖魔是什么祷杈? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮渗饮,結(jié)果婚禮上但汞,老公的妹妹穿的比我還像新娘。我一直安慰自己互站,他們只是感情好私蕾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胡桃,像睡著了一般踩叭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天容贝,我揣著相機(jī)與錄音自脯,去河邊找鬼。 笑死斤富,一個胖子當(dāng)著我的面吹牛膏潮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播满力,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼焕参,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了脚囊?” 一聲冷哼從身側(cè)響起龟糕,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悔耘,沒想到半個月后讲岁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衬以,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年缓艳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片看峻。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡阶淘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出互妓,到底是詐尸還是另有隱情溪窒,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布冯勉,位于F島的核電站澈蚌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏灼狰。R本人自食惡果不足惜宛瞄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望交胚。 院中可真熱鬧份汗,春花似錦、人聲如沸蝴簇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽军熏。三九已至轩猩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背均践。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工晤锹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人彤委。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓鞭铆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親焦影。 傳聞我的和親對象是個殘疾皇子车遂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

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

  • 內(nèi)存泄漏的定義 不再使用的對象持續(xù)占用內(nèi)存或者內(nèi)存得不到及時釋放,從而造成內(nèi)存空間的浪費(fèi)稱為內(nèi)存泄漏斯辰。嚴(yán)重時會產(chǎn)生...
    Samuel_Tom閱讀 940評論 0 2
  • 概念 內(nèi)存泄漏是因?yàn)槌钟袑ο箝L期引用舶担,導(dǎo)致對象無法被 GC 回收。 為了避免這種情況彬呻,我們可以選擇在對象生命周期結(jié)...
    hongjay閱讀 1,460評論 1 2
  • 原文 什么是內(nèi)存泄漏衣陶? 每個應(yīng)用程序都需要內(nèi)存作為資源來完成其工作。為了確保Android中的每個應(yīng)用都有足夠的內(nèi)...
    公子小水閱讀 557評論 0 1
  • Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題闸氮。內(nèi)存泄漏...
    _痞子閱讀 1,636評論 0 8
  • 內(nèi)存泄漏 Java 內(nèi)存分配策略 Java 程序運(yùn)行時的內(nèi)存分配策略有三種,分別是靜態(tài)分配,棧式分配,和堆式分配剪况,...
    酷酷de熊閱讀 331評論 0 0