一.什么是內(nèi)存泄露
Android 內(nèi)存泄漏指的是進程中某些對象(垃圾對象)已經(jīng)沒有使用價值了,但是它們卻可以直接或間接地引用到 gc roots 導致無法被 GC 回收硝拧。無用的對象占據(jù)著內(nèi)存空間验懊,使得實際可使用內(nèi)存變小缩膝,形象地說法就是內(nèi)存泄漏了惊来。
泄露場景:
1.類的靜態(tài)變量持有大數(shù)據(jù)對象
靜態(tài)變量長期維持到大數(shù)據(jù)對象的引用攀痊,阻止垃圾回收桐腌。
2.非靜態(tài)內(nèi)部類的靜態(tài)實例
非靜態(tài)內(nèi)部類會維持一個到外部類實例的引用,如果非靜態(tài)內(nèi)部類的實例是靜態(tài)的苟径,就會間接長期維持著外部類的引用案站,阻止被回收掉。
3.資源對象未關閉
資源性對象如Cursor棘街、File蟆盐、Socket,,應該在使用后及時關閉遭殉。未在finally中關閉舱禽,會導致異常情況下資源對象未被釋放的隱患。
4.Handler臨時性內(nèi)存泄露
Handler通過發(fā)送Message與主線程交互恩沽,Message發(fā)出之后是存儲在MessageQueue中的誊稚,有些Message也不是馬上被處理的。在Message中存在一個target,是Handler的一個引用罗心,如果Message在Queue中存在的時間越長里伯,就會導致Handler無法被回收,如果Handler是非靜態(tài)的渤闷,則會導致Activity或者Service不會被回收疾瓮。
由于AsyncTask內(nèi)部也是Handler機制,同樣存在泄露風險飒箭。
預防
不要維持到Activity的長久引用狼电,對activity的引用應該和activity本身有相同的生命周期。
盡量使用context-application代替context-activity弦蹂。
Activity中盡量不要使用非靜態(tài)內(nèi)部類肩碟,可以使用靜態(tài)內(nèi)部類和WeakReference代替。
監(jiān)測
靜態(tài)檢測
靜態(tài)檢測主要是檢測資源未關閉的情況凸椿,Eclipse 和 Android Studio 都可以檢測出 IO 或者 Socket 未關閉的情況削祈,然后在 finally 中關閉即可。
動態(tài)監(jiān)測
動態(tài)檢測主要是依靠MAT這個工具脑漫,或者查看AndroidStudio中的Monitors 或者采用三方庫LeakCanary等髓抑。