內(nèi)存泄漏的產(chǎn)生
Android虛擬機中把內(nèi)存分為兩部分,一部分為堆空間,里面儲存的是對象的實例,需要開發(fā)者主動創(chuàng)建,垃圾回收主要作用在這部分;另一部分為棧空間,儲存一些全局引用和靜態(tài)變量等值,該空間的分配與回收由系統(tǒng)機制決定,垃圾回收機制不作用這塊區(qū)域。
內(nèi)存泄漏也稱作“存儲滲漏”,用動態(tài)存儲分配函數(shù)動態(tài)開辟的空間,在使用完畢后未釋放,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元。直到程序結(jié)束。即所謂內(nèi)存泄漏。
內(nèi)存泄漏簡單地說就是申請了一塊內(nèi)存空間,使用完畢后沒有釋放掉。它的一般表現(xiàn)方式是程序運行時間越長,占用內(nèi)存越多,最終用盡全部內(nèi)存,整個系統(tǒng)崩潰。由程序申請的一塊內(nèi)存,且沒有任何一個指針指向它,那么這塊內(nèi)存就泄露了。
靜態(tài)變量的生命周期基本和應(yīng)用同周期
(防止)內(nèi)存泄漏的幾點建議
1、盡量不要用生命周期長于Activity的對象來持有Activity的引用。
2、在需要傳入Context的時候盡量考慮使用Application的Context而不是Activity的
3、在Activity中盡量避免使用生命周期不受控制的非靜態(tài)類型的內(nèi)部類,可以使用靜態(tài)類型的內(nèi)部類加上弱引用的方式實現(xiàn)。
Android應(yīng)用內(nèi)存泄漏的的原因有以下幾個:
1、查詢數(shù)據(jù)庫后沒有關(guān)閉游標cursor。
2、 使用Adapter作為適配器時沒有復(fù)用convertView??梢詤⒖糒istView與BaseAdapter優(yōu)化。
3、bitmap沒有回收, Bitmap對象不在使用時調(diào)用recycle()釋放內(nèi)存??梢詤⒖糂itmap相關(guān):管理Bitmap內(nèi)存。
4、注冊對象后沒有反注冊,比如Broadcast Receiver等。
5、handler問題,如果handler是非靜態(tài)的,會導(dǎo)致Activity或者Service不被回收,所以應(yīng)當注冊為靜態(tài)內(nèi)部類,同時在onDestroy時停止線程:mThread.getLooper().quit();
6 、對象被生命周期長的對象引用,如activity被靜態(tài)集合引用導(dǎo)致activity不能釋放,Activity被靜態(tài)引用,特別是緩存bitmap時,解決方法可以考慮使用Application的context代替Activity的context。
7、WebView的泄露問題:在魅族上面發(fā)現(xiàn)webView打開再關(guān)閉就會內(nèi)存泄露..目前使用的解決方法是在webview外面嵌套一層layout作為 container,在Activity的onDestroy中調(diào)用container.removeAllViews()方法。
8、Dialog導(dǎo)致Window泄露,如果需要在dialog依附的Activity銷毀前沒有調(diào)用dialog.dismiss().會導(dǎo)致Activity泄露
檢測內(nèi)存泄露的方法
Android Studio 自帶的 Memory Monitor,手動觸發(fā)GC可以看得比較直觀,但是dump出來的文件需要處理才能用MAT打開,利用 sdk/platforms-tool/ 下的 hprof-conv 文件,命令為: /hprof-conv source output
內(nèi)存泄漏如何解決
通過內(nèi)存分析工具 MAT(Memory Analyzer Tool),找到內(nèi)存泄露的對象