Android 性能優化:內存泄漏

1、定義
  1. 定義:內存不在使用,無法歸還給應用程序的現象。
2、影響
  1. 影響:容易使應用程序發生內存溢出(Out Of Memory )。OOM(定義:應用程序所需內存 大於 安卓系統分配的內存);安卓系統爲每個應用程序分配的內存有限,內存溢出容易導致應用程序崩潰。
3、原因
  1. 本質原因:持有引用者的生命週期 大於 被引用者的生命週期。導致本該回收的對象無法被回收。
4、Android 內存管理機制
  1. 定義:Android 內存管理:內存分配 和 內存回收。
  2. 管理的對象:進程、對象、變量。
  3. 管理的角色:Application Framework、Dalvik 虛擬機、Linux 內核。Application Framework 和 Linux 內核 負責 進程;Dalvik 虛擬機 負責 對象、變量 內存管理。
  4. 進程的內存分配與回收
    1、分配:ActivityManagerService 管理進程的內存分配。
    2、回收:1.Application Framework 按優先級決定回收類型(前臺進程>可見進程>服務進程>後臺進程>空進程)。2.Linux 內核回收具體進程。
  5. 對象、變量的內存分配與回收
內存分配策略 使用內存空間 存儲數據 特點
靜態分配 方法區 類信息、常量、靜態變量 1.編譯時分配好。2.存在整個程序的運行區間。
棧分配 棧區 局部變量(基本數據類型、對象的引用) 1.方法執行時,程序自動在棧中分配內存,方法結束,自動釋放內存。2.效率高。3.內存容量有限。
堆分配 堆區 對象的實例、實例的成員變量 1.創建對象,程序在堆中分配內存。2.Java 垃圾回收器(垃圾回收算法),回收內存
算法名稱 算法思想 優點 缺點 應用場景
標記-清除 算法 1.標記階段:標記出所以要回收的對象。2.清除階段:清除所以被標記的對象。 實現簡單 1.效率問題:標記 和 清除 兩個過程,效率低。2.空間問題:產生大量不連續的內存碎片。 對象存活率高;垃圾回收頻率低。(如:老年代)
複製 算法 1.將內存分爲大小相等的兩塊,每次使用其中的一塊。2.當使用的這塊內存用完,將還存活的對象複製到另一塊內存。3.最後將使用的那塊內存一次性清理掉。 1.解決標記-清除效率問題:每次回收內存一半區域。2.解決標記-清除空間問題:將存活對象按順序複製到另一塊內存。 1.每次使用的內存縮小爲原來一半。2.對象存活率高的情況要做較多複製操作,效率低。 對象存活率低;垃圾回收頻率高。(如:新生代)
標記-整理 算法 1.標記階段:標記出所以要回收的對象。2.整理階段:讓所有存活的對象都向一端移動。3.清除階段:清除所以被標記的對象。 1.解決標記-清除效率問題:一次清除端外區域。2.解決標記-清除空間問題:存活的對象移到一端。 步驟繁瑣:標記、整理、清除。 對象存活率高;垃圾回收頻率低。(如:老年代)
分代回收 算法 根據對象的存活週期將堆內存分爲:新生代和老年代。1.新生代:對象存活率低;垃圾回收頻率高。採用 複製算法。2.老年代:對象存活率高;垃圾回收頻率低。採用 標記-清除、標記-整理 算法。 效率高,空間利用率高:根據不同區域特點選擇不同垃圾回收算法 虛擬機採用此算法

如何判斷一個對象是否可以被回收:
1、引用計數算法:引用計數爲 0 的對象實例可以被當作垃圾回收。(很難解決對象相互引用的問題)。
2、可達性分析算法:不可到達的對象表示可以回收。

5、常見內存泄漏原因及解決方案

1、集合類
2、static 關鍵字修飾成員變量
3、非靜態內部類 / 匿名類
4、資源對象使用後未關閉
5、其它(Context、WebView、Adapter)

  1. 集合類
    1、原因:集合添加元素,引用了該元素對象,導致對象不可以被回收,導致內存泄漏。
    2、解決方案:集合使用後清除對象。(如:list.clear();list = null ;)
  2. static 關鍵字修飾成員變量
    1、原因:static 修飾的生命週期 = 應用程序的生命週期。(如:static Context = mContext;)
    2、解決方案:1、使用 Application 的 Context。2、使用弱引用(WeakReference)。
  3. 非靜態內部類 / 匿名類
    1、原因:非靜態內部類 / 匿名類 默認持有外部類的引用。
    2、解決方案:1、使用 Application 的 Context。2、使用弱引用(WeakReference)。3、使用靜態內部類。(如:多線程 Thread、Handler 等)。
  4. 資源對象使用後未關閉
    1、原因:資源對象使用後未關閉,資源將不會被回收,導致內存泄漏。
    2、解決方案: 資源對象使用後關閉。(如:廣播 BroadcastReceiver-unregisterReceiver()、文件流-InputStream.close()、數據庫遊標 Cursor-Cursor.close、圖片資源 Bitmap-Bitmap.recycle();Bitmap = null;、動畫停止)。
  5. 其它(Context、WebView、Adapter)
    1、Context:使用 Application 的 Context;使用弱引用。
    2、WebView:動態創建 WebView;不使用時銷燬。
    3、Adapter:如 ListView:使用緩存 convertView;使用 ViewHolder。或 RecycleView 替代。
5、輔助分析內存泄漏
  1. Android Profiler:Androidstudio 3.0自帶工具,分析 CPU、MEMORY、NETWORK 等。
  2. LeakCanary:Square 出品的檢測內存泄漏的開源庫。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章