本文來自於Dev Club 開發者社區,非經做者贊成,請勿轉載,原文地址:http://dev.qq.com/topic/57d14047603a5bf1242ad01bphp
內存泄漏問題大約是Android開發者最煩惱的問題之一了,項目中連續遇到幾個內存泄漏問題,這裏簡單總結下檢查分析內存泄漏的一些工具與方法。java
你們都知道,java是有垃圾回收機制的,這使得java程序員比C++程序員輕鬆了許多,存儲申請了,不用心心念念要加一句釋放,java虛擬機會派出一些回收線程兢兢業業不定時地回收那些再也不被須要的內存空間(注意回收的不是對象自己,而是對象佔據的內存空間)。程序員
Q1:什麼叫再也不被須要的內存空間?微信
**答:**Java沒有指針,全憑引用來和對象進行關聯,經過引用來操做對象。若是一個對象沒有與任何引用關聯,那麼這個對象也就不太可能被使用到了,回收器即是把這些「無任何引用的對象」做爲目標,回收了它們佔據的內存空間。app
Q2:如何分辨爲對象無引用?eclipse
**答:**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<Object>(activity)。
**PS:**與強引用和軟引用相比,弱引用不會被回收器當作一個「有效」的引用,不會影響其引用對象的釋放。實際上,垃圾回收器會堅決果斷地回收只有弱引用的對象~
4)在 LeakThread中咱們每隔一段時間檢測一下ref.get() 是否爲空,爲空說明activity已被釋放。不爲空能夠手動觸一次發gc;若是超過一段時間,好比50s,頁面對象還未被清理,咱們能夠推斷內存泄漏的發生.
5)當內存泄漏發生時,提示給開發者,並自動dump出.prof文件。
由於代碼檢測不是這裏的重點,代碼就不貼了,只記思路。
發現可能出現內存泄漏時,咱們須要對.prof文件進行分析,方能快速定位到是哪一個倒黴傢伙致使了內存泄漏
打開DDMS ,Eclipse 能夠切到DDMS視圖,Android studio能夠從Tools-Android-Android device monitor進入DDMS
找到app的進程,在進程上方點擊「update heap」按鈕,能夠先主動出發一次GC,待內存佔用數據稍微穩定下來後 點擊「Dump HProf File」,即可以導出.prof文件
Android studio能夠直接打開prof文件。點開Analyzer Tasks的面板,點擊右上角的開始按鈕。
分析完成後,發生內存泄漏的頁面對象會出如今Analysis Results面板-Leak Activityes的目錄下。
如圖,原來泄漏發生是LoadingRoomActivity的鍋!
在官網能夠下載到它:
雖然MAT不會準確告訴你你的代碼哪泄漏了,可是它會給你發現哪泄露的數據和線索。
在MAT中打開.prof頁面,你可能會遇到一點小挫折:
如上圖,可能會彈出 ‘Parsing heap dump from xxx has encountered a proplem’ 的錯誤彈窗
這是由於文件版本和編輯器能支持的版本有衝突的緣由。
解決方案以下:
Sdk安裝目錄下platform-tools裏有一個hprof-conv工具能夠解決該問題。在cmd控制檯執行:
hprof-conv input.hprof output.hprof
從新再MAT打開output.hprof 就能夠打開了~
值得一提的是,若是你dump出的文件太大的話,也有可能發現打不開的現象,這時候,打開安裝MAT目錄下的MemoryAnalyzer.ini 把-XmX改大些重啓便可。可是也不要改得比你機器的可用內存還大,不能太貪心哈哈~
經過MAT打開.phrof文件後,會彈出Overview 和 Leak Suspects 2個標籤頁。
Leak Suspects標籤頁可見以下圖:
Leak Suspects視圖展現了app內存佔用的比例,淺色是空閒的內存,其餘是內存佔用的空間。每塊內存對應的問題也都列在下面。點開每一個Problem Suspect下的details,能夠看到有哪些類的實例佔用了內存和佔用大小等信息~
此時咱們已經有了懷疑的目標,爲了更清晰地查看,咱們能夠回到Overview頁面,打開Histogram頁面:
在打開的Histogram標籤頁中,咱們填入檢測對象,在列出的匹配項中過濾掉對象的非強引用。
到這裏咱們就能夠看到,是哪一個壞蛋hold住了你的對象了。MAT可以給到的支持也就到這裏,接下來,仍是須要你根據這些線索到代碼中尋找判別和修正了~``
更多精彩內容歡迎關注騰訊優測的微信公衆帳號:
騰訊優測是專業的移動雲測試平臺,爲應用、遊戲,H5混合應用的研發團隊提供產品質量檢測與問題解決服務。不只在線上平臺提供「全面兼容測試」、「雲手機」等多種質量檢測工具,同時在線下爲VIP客戶配備專家團隊,提供定製化綜合測試解決方案。真機實驗室配備上千款手機,覆蓋億級用戶,7*24小時在線運行,爲各種測試工具提供支持。