本文來自於Dev Club 開發者社區,非經作者同意,請勿轉載,原文地址:http://dev.qq.com/topic/57d14047603a5bf1242ad01b
導語
內存泄漏問題大約是Android開發者最煩惱的問題之一了,項目中連續遇到幾個內存泄漏問題,這里簡單總結下檢查分析內存泄漏的一些工具與方法。
一、什么是內存泄漏?
大家都知道,java是有垃圾回收機制的,這使得java程序員比C++程序員輕松了許多,存儲申請了,不用心心念念要加一句釋放,java虛擬機會派出一些回收線程兢兢業業不定時地回收那些不再被需要的內存空間(注意回收的不是對象本身,而是對象占據的內存空間)。
Q1:什么叫不再被需要的內存空間?
答:Java沒有指針,全憑引用來和對象進行關聯,通過引用來操作對象。如果一個對象沒有與任何引用關聯,那么這個對象也就不太可能被使用到了,回收器便是把這些“無任何引用的對象”作為目標,回收了它們占據的內存空間。
Q2:如何分辨為對象無引用?
答:2種方法
-
引用計數法
直接計數,簡單高效,Python便是采用該方法。但是如果出現 兩個對象相互引用,即使它們都無法被外界訪問到,計數器不為0它們也始終不會被回收。為了解決該問題,java采用的是b方法。 -
可達性分析法
這個方法設置了一系列的“GC Roots”對象作為索引起點,如果一個對象 與起點對象之間均無可達路徑,那么這個不可達的對象就會成為回收對象。這種方法處理 兩個對象相互引用的問題,如果兩個對象均沒有外部引用,會被判斷為不可達對象進而被回收(如下圖)。
Q3:有了回收機制,放心大膽用不會有內存泄漏?
答:答案當然是No!
雖然垃圾回收器會幫我們干掉大部分無用的內存空間,但是對於還保持着引用,但邏輯上已經不會再用到的對象,垃圾回收器不會回收它們。這些對象積累在內存中,直到程序結束,就是我們所說的“內存泄漏”。
當然了,用戶對單次的內存泄漏並沒有什么感知,但當泄漏積累到內存都被消耗完,就會導致卡頓,崩潰。
二、發現內存泄漏
內存泄漏不可小視,在Android開發中,比如說一個Activity頁面會占用許多資源開銷,如果頁面發生泄漏,關閉以后頁面沒有能被系統回收,對應用程序的傷害是很大的。
Q1:在Android開發測試中一般如何發現內存泄漏的發生呢?
答:
方法1:反復操作觀察內存變化
內存泄漏常見變現為程序使用時間越長,內存占用越多。那我們通過反復操作應用,比如反復點開/關閉頁面,觀察內存變化狀況是否一點點上漲,可以粗略地判斷是否有內存泄漏
1.通過 DDMS 中的 heap 工具,可以查看應用內存的使用情況
2.Android studio也可以方便查看
方法2:通過代碼檢測Activity泄漏
基本思路:
1)debug版本可以起一個長期工作的線程LeakThread在后台專門做泄漏檢測
2)向Application注冊一個 頁面生命周期 的監聽:application.registerActivityLifecycleCallbacks
3)在監聽類中對 onActivityDestoryed(Activity activity) 的事件回調做處理:
如果一個Activity走到onDestroy,那么這個Activity對象就是需要被回收的目標。
我們聲明一個檢測對象的弱引用ref = new WeakReference