1.內存泄漏是什么
- 一句話概括:就是GC垃圾回收機制漏掉的垃圾對象绊序,無法回收
- 內存泄漏過多就會造成內存溢出
2.什么是垃圾回收機制?
就是當對象不具備任何引用的時候岗宣,可被回收
3.GC ROOT Tracing 算法
GC Root Tracing
- 被GC Root 引用的對象不可被回收
- 沒有被GC Root Obj所持有的對象可以被回收
4.可以作為GC Root引用的點是(不被回收):
- java stack中引用的對象
- 方法區(qū)中靜態(tài)引用指向的對象
- 方法去中常量引用指向的對象
- Native方法中jni引用的對象
- Thread—活著的線程
5.常見的內存泄漏案例:
-
1:單例造成的內存泄漏
- 解決方案
- 將該屬性的引用方式改為弱引用;
- 如果傳入Context,使用ApplicationContext;
- 解決方案
-
2: InnerClass匿名內部類
- 在Java中趁猴,非靜態(tài)內部類 和 匿名類 都會潛在的引用它們所屬的外部類儡司,但是余指,靜態(tài)內部類卻不會。如果這個非靜態(tài)內部類實例做了一些耗時的操作碉碉,就會造成外圍對象不會被回收垢粮,從而導致內存泄漏靠粪。
- 解決方案
- 將內部類變成靜態(tài)內部類;
- 如果有強引用Activity中的屬性毫蚓,則將該屬性的引用方式改為弱引用;
- 在業(yè)務允許的情況下元潘,當Activity執(zhí)行onDestory時柬批,結束這些耗時任務;
-
3:Activity Context 的不正確使用
- 在Android應用程序中通承涠可以使用兩種Context對象:Activity和Application洛姑。當類或方法需要Context對象的時候常見的做法是使用第一個作為Context參數。這樣就意味著View對象對整個Activity保持引用参咙,因此也就保持對Activty的所有的引用硫眯。
- 解決方案
- 使用ApplicationContext代替ActivityContext两入,因為ApplicationContext會隨著應用程序的存在而存在,而不依賴于activity的生命周期择葡;
- 對Context的引用不要超過它本身的生命周期剃氧,慎重的對Context使用“static”關鍵字朋鞍。Context里如果有線程,一定要在onDestroy()里及時停掉更舞。
-
4:Handler引起的內存泄漏
- 當Handler中有延遲的的任務或是等待執(zhí)行的任務隊列過長恨狈,由于消息持有對Handler的引用,而Handler又持有對其外部類的潛在引用贝搁,這條引用關系會一直保持到消息得到處理芽偏,而導致了Activity無法被垃圾回收器回收,而導致了內存泄露膀哲。
- 解決方案
- 可以把Handler類放在單獨的類文件中某宪,或者使用靜態(tài)內部類便可以避免泄露;
- 如果想在Handler內部去調用所在的Activity,那么可以在handler內部使用弱引用的方式去指向所在Activity.使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關系的目的锐朴。
-
5:注冊監(jiān)聽器的泄漏
- 解決方案
- 使用ApplicationContext代替ActivityContext;
- 在Activity執(zhí)行onDestory時焚志,調用反注冊;
- 解決方案
6:Cursor,Stream沒有close壶谒,View沒有recyle
-
7:集合中對象沒清理造成的內存泄漏
- 在Activity退出之前汗菜,將集合里的東西clear贵少,然后置為null,再退出程序。
-
8: WebView造成的泄露
- 當我們不要使用WebView對象時吼肥,應該調用它的destory()函數來銷毀它缀皱,并釋放其占用的內存,否則其占用的內存長期也不能被回收表箭,從而造成內存泄露钮莲。
9:構造Adapter時彼水,沒有使用緩存的ConvertView
6.使用AndroidStudio進行內存分析
步驟如下:
圖1:
圖1
圖2:
![圖2](https://raw.githubusercontent.com/sheltonliu/sheltonliu.github.io/hexo/blog/MarkdownPhotos/2017/07/10/memory_tool2.png)
圖2
7.通過MAT工具進行分析
第一步:如下圖先導出標準的hprof文件〔鹞海可以生成兩個hprof文件渤刃,通過MAT比較分析。
圖1
第二步:打開MAT工具略号,可以單獨下載這個插件下載
圖2
第三步:導入兩個hprof文件璃哟,根據下圖的步驟進行比較分析
圖3
第四步:按照下圖步驟選擇
圖4
最后:找到未釋放的引用
圖5