面試中經(jīng)常會問到什么是內(nèi)存泄露?什么又是內(nèi)存溢出扫沼?
今天就來好好總結(jié)一下出爹。
一、內(nèi)存泄露 ( memory leak )
垃圾回收器無法回收原本應(yīng)該被回收的對象充甚,這個對象便引發(fā)了內(nèi)存泄露以政。
內(nèi)存泄露的危害:
(1)過多的內(nèi)存泄露最終會導致內(nèi)存溢出(OOM)
(2)內(nèi)存泄露導致可用內(nèi)存不足,會觸發(fā)頻繁GC伴找,不管是Android2.2以前的單線程GC還是現(xiàn)在的CMS和G1盈蛮,都有一部分的操作會導致用戶線程停止(就是所謂的Stop the world),從而導致UI卡頓技矮。
二抖誉、內(nèi)存溢出(OOM-out of memory)
程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用衰倦,出現(xiàn)out of memory袒炉;比如申請了一個integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出樊零。
Android為每個進程設(shè)置Dalvik Heap Size閾值我磁,這個閾值在不同的設(shè)備上會因為RAM大小不同而各有差異孽文。如果APP想要分配的內(nèi)存超過這個閾值,就會發(fā)生OOM夺艰。
ActivityManager.getMemoryClass()可以查詢當前APP的Heap Size閾值芋哭,單位是MB。
在3.x以前郁副,Bitmap分配在Native heap中减牺,而在4.x之后,Bitmap分配在Dalvik或ART的Java heap中存谎。
Android 2.x系統(tǒng)拔疚,當dalvik allocated + native allocated + 新分配的大小 >= dalvik heap 最大值時候就會發(fā)生OOM,也就是說在2.x系統(tǒng)中,考慮native heap對每個進程的內(nèi)存限制。
Android 4.x系統(tǒng),廢除了native的計數(shù)器,類似bitmap的分配改到dalvik的java heap中申請峦耘,只要allocated + 新分配的內(nèi)存 >= dalvik heap 最大值的時候就會發(fā)生OOM(art運行環(huán)境的統(tǒng)計規(guī)則還是和dalvik保持一致),也就是說在4.x系統(tǒng)中顷歌,不考慮native heap對每個進程的內(nèi)存限制物咳,native heap只會收到本機總內(nèi)存(包括RAM以及SWAP區(qū)或分頁文件)的限制。
三旬昭、內(nèi)存泄露的原因
比如當你向系統(tǒng)申請分配內(nèi)存進行使用(new)篙螟,可是使用完了以后卻不歸還(delete),結(jié)果你申請到的那塊內(nèi)存你自己也不能再訪問(也許你把它的地址給弄丟了)问拘,而系統(tǒng)也不能再次將它分配給需要的程序遍略。
1.資源對象沒關(guān)閉
如Cursor,F(xiàn)ile等資源骤坐。他們會在finalize中關(guān)閉绪杏,但這樣效率太低。容易造成內(nèi)存泄漏
SQLiteCurost,當數(shù)據(jù)量大的時候容易泄漏
2.使用Adapter時纽绍,沒有使用系統(tǒng)緩存的converView
3.沒有即時調(diào)用recycle()釋放不再使用的bitmap
4.使用application的context來替代activity相關(guān)的context
不要讓生命周期長于Activity的對象持有到Activity的引用
5.廣播注冊沒取消造成內(nèi)存泄露
6.Handler應(yīng)該申明為靜態(tài)對象蕾久, 并在其內(nèi)部類中保存一個對外部類的弱引用。
7拌夏、Context持有導致內(nèi)存泄漏
Activity Context被傳遞到其他實例中僧著,這可能導致自身被引用而發(fā)生泄漏。
解決:對于大部分非必須使用Activity Context的情況(創(chuàng)建Dialog的Context必須是Activity Context)障簿,應(yīng)該使用Application Context盹愚。
8、記得注銷監(jiān)聽器
注冊監(jiān)聽器的時候會add Listener站故,不要忘記在不需要的時候remove掉Listener皆怕。
內(nèi)存泄露會引發(fā)內(nèi)存溢出。
參考連接:http://blog.csdn.net/mxm691292118/article/details/51020023