一.什么是內存泄露
Android 內存泄漏指的是進程中某些對象(垃圾對象)已經沒有使用價值了,但是它們卻可以直接或間接地引用到 gc roots 導致無法被 GC 回收。無用的對象占據著內存空間,使得實際可使用內存變小,形象地說法就是內存泄漏了。
泄露場景:
1.類的靜態變量持有大數據對象
靜態變量長期維持到大數據對象的引用,阻止垃圾回收。
2.非靜態內部類的靜態實例
非靜態內部類會維持一個到外部類實例的引用,如果非靜態內部類的實例是靜態的,就會間接長期維持著外部類的引用,阻止被回收掉。
3.資源對象未關閉
資源性對象如Cursor、File、Socket,,應該在使用后及時關閉。未在finally中關閉,會導致異常情況下資源對象未被釋放的隱患。
4.Handler臨時性內存泄露
Handler通過發送Message與主線程交互,Message發出之后是存儲在MessageQueue中的,有些Message也不是馬上被處理的。在Message中存在一個target,是Handler的一個引用,如果Message在Queue中存在的時間越長,就會導致Handler無法被回收,如果Handler是非靜態的,則會導致Activity或者Service不會被回收。
由于AsyncTask內部也是Handler機制,同樣存在泄露風險。
預防
不要維持到Activity的長久引用,對activity的引用應該和activity本身有相同的生命周期。
盡量使用context-application代替context-activity。
Activity中盡量不要使用非靜態內部類,可以使用靜態內部類和WeakReference代替。
監測
靜態檢測
靜態檢測主要是檢測資源未關閉的情況,Eclipse 和 Android Studio 都可以檢測出 IO 或者 Socket 未關閉的情況,然后在 finally 中關閉即可。
動態監測
動態檢測主要是依靠MAT這個工具,或者查看AndroidStudio中的Monitors 或者采用三方庫LeakCanary等。