android 內(nèi)存泄漏總結(jié)
前言
內(nèi)存泄漏很危險(xiǎn)。輕則卡頓,重則oom。
這種東西寫代碼的時(shí)候注意一下就能避免90%的內(nèi)存泄漏,
只要寫代碼的時(shí)候遇到想一下你就可以避免了,免得后面為了找內(nèi)存泄漏各種排查,得不嘗試!!
最后會總結(jié)一下常見的內(nèi)存泄漏。
導(dǎo)致內(nèi)存泄漏的原因
總結(jié)來說就是:
本該被jvm回收的生命周期短對象卻被生命生命周期長的對象直接或間接的所持有導(dǎo)致短對象無法釋放。有種藕斷絲連的感覺,哈哈...
排查之法-MAT(MemoryAnalyzerTools)
MAT 是一個(gè)根據(jù)堆的內(nèi)存信息檢測內(nèi)存對象之間的引用鏈的關(guān)系,根據(jù)這個(gè)關(guān)系我們就可以知道哪些對象內(nèi)存泄漏了。具體的操作流程網(wǎng)上有很多,這里就不多寫了。
排查之法-LeakCanary
LeakCanary是一個(gè)檢測內(nèi)存泄露的開源類庫,地址:
https://github.com/square/leakcanary
常見的內(nèi)存泄漏
- 單例造成的內(nèi)存泄漏,一般是傳入的是Context的問題,解決方法:傳入 Application 的 Context。
- 匿名內(nèi)部類/非靜態(tài)內(nèi)部類和異步線程造成的內(nèi)存泄漏,解決方法:靜態(tài)內(nèi)部類,靜態(tài)內(nèi)部類中使用弱引用來引用外部類的成員變量。
- 避免使用 static 成員變量,它的生命周期和應(yīng)用的生命周期一樣長。
- 資源未關(guān)閉造成的內(nèi)存泄漏,比如:BraodcastReceiver,ContentObserver,F(xiàn)ile,Cursor,Stream,Bitmap等資源的使用,應(yīng)該在Activity銷毀時(shí)及時(shí)關(guān)閉或者注銷,否則這些資源將不會被回收,造成內(nèi)存泄漏。
- bitmap的使用問題:加載可以使用色彩模式為rgb565的方式節(jié)省內(nèi)存的開銷。釋放時(shí)調(diào)用recyle()方法因?yàn)榧虞dBitmap對象的內(nèi)存空間:java+c 兩部分內(nèi)存,調(diào)用recyle()是釋放c內(nèi)存的空間。
- handler造成的內(nèi)存泄漏,因?yàn)閔andler的生命周期和activity或者view的生命周期是不一樣的,它屬于Thread-Local型的,很容易導(dǎo)致無法正確釋放。關(guān)系:Handler、Message和MessageQueue都是相互關(guān)聯(lián)在一起的,如果Handler發(fā)送的Message延時(shí)處理,則該Message及發(fā)送它的 Handler對象將被線程 MessageQueue一直持有。那么持有Handler的對象(view/activity)就泄漏了。