1. 程式人生 > >應用記憶體洩露問題分析例項

應用記憶體洩露問題分析例項

記憶體洩露,這個應用開發中比較容易出現的問題,由於短時間內難以測出來一般都比較難以發現,只能靠開發者的警覺性來避免,長時間的Monkey測試就成為一個可行的手段。

Monkey測試能給出一個直觀的記憶體變化曲線和日誌,GC日誌在記憶體緊張時都會打印出測試程序的記憶體資訊。往往報錯資訊也會指明是 java.lang.OutOfMemoryError但是報這個異常的地方往往並不是記憶體洩露的位置,它只是比較倒黴正好申請記憶體發現不足了。

直接找重點GC日誌類似這樣:

 I art     : Starting a blocking GC Alloc
 I art     : Starting a blocking GC Alloc
 I art     : Waiting for a blocking GC Alloc
 I art     : Alloc sticky concurrent mark sweep GC freed 5223(480KB) AllocSpace objects, 5(100KB) LOS objects, 1% free, 189MB/192MB, paused 2.153ms total 35.644ms
 I art     : WaitForGcToComplete blocked for 21.733ms for cause Alloc
 I art     : Starting a blocking GC Alloc

相信網上解釋這幾句日誌的部落格已經很多了,就是現在已用記憶體189M上限是192M,應用下一次申請超過剩餘操作限制了就OOM了。

首先確認資訊是否符合系統設定

檢視系統設定單個程序的記憶體上限

adb shell
[email protected]:/ # getprop|grep heapgrowthlimit
[dalvik.vm.heapgrowthlimit]: [192m]

沒錯就是配置的192M,你的應用消耗的太多了,肯定是有記憶體洩露了的。

那麼怎麼查詢問題呢,通過這個日誌直接分析不到問題,只能根據日誌看出應用的大致操作流程,不過Monkey幾萬次估計所有邏輯都走到了,還是對整個應用內容的使用情況進行檢查。

Android上應用開發常見的記憶體洩露的型別可以看看大神寫的http://blog.csdn.net/u010687392/article/details/49909477

其實自從Bitmap的記憶體分配到java層之後這一類很容易搞定了,用弱引用的快取直接就安了,這個直接全程式碼搜尋一下挨個改就行了;

其他的同樣顯性的BraodcastReceiver,ContentObserver,File,Cursor,Stream這一類全程式碼搜尋改就行了;

剩下的比較難找的就是Activity的洩露同時也是應用主要的記憶體洩露問題,這個如果對程式碼很熟悉也可以對程式碼中所有的context、handler等搜尋處理,但是如果封裝層次比較深模組程式碼量比較大的情況下,會花費較長的時間。

首先可以用adb shell dumpsys meminfo package name看看當前程序的記憶體使用情況

Applications Memory Usage (kB):
Uptime: 774504 Realtime: 774504


** MEMINFO in pid 5592 [package namer] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     9076     8980        0        0    12776    12483      292
  Dalvik Heap    12276    12200        0        0    14499    13738      761
 Dalvik Other      956      956        0        0
        Stack      328      328        0        0
      Gfx dev     3926     3056        0        0
    Other dev        5        0        4        0
     .so mmap     2320      464       60        0
    .apk mmap      136        0       16        0
    .ttf mmap      346        0      204        0
    .dex mmap     2524        0     2520        0
    .oat mmap     4493        0     1756        0
    .art mmap     2465     1196      628        0
   Other mmap       51        4       40        0
   EGL mtrack    28224    28224        0        0
      Unknown      233      232        0        0
        TOTAL    67359    55640     5228        0    27275    26221     1053


 Objects
               Views:      271         ViewRootImpl:        1
         AppContexts:        7           Activities:        1
              Assets:        3        AssetManagers:        3
       Local Binders:       22        Proxy Binders:       32
       Parcel memory:        8         Parcel count:       34
    Death Recipients:        0      OpenSSL Sockets:        0


 SQL
         MEMORY_USED:     1206
  PAGECACHE_OVERFLOW:      946          MALLOC_SIZE:       62


 DATABASES
      pgsz     dbsz   Lookaside(b)          cache  Dbname
         1     1673            281     834/125/25  /data/data/package name/databases/sqlit.db

如果此時這裡的Activities與目前應用的執行狀態不一致,比如目前退出了應該為零但是這裡還有數值,很顯然就是有Context洩露了(其實這裡還能看到很多其他記憶體資料),這時候就可以使用MAT工具進行分析。

先生成一個hprof檔案,然後用MAT工具開啟,直接在總覽介面選擇

Histogram: Lists number of instances per class

這時會將所有當前物件及其數量Heap大小一起列出來,非常的多,可以直接輸入Activity或者其他關鍵字進行搜尋。

如果其中的Objects數目與當前應用執行情況不一致就是有問題的地方。

在此條記錄上右鍵選擇Merge Shortest Paths to GC Roots --> with all references就可以列出當前物件到GC Root之間的最短引用鏈,找到並打斷這個引用關係就是我們工作

這個栗子由於專案關係就不能貼上具體程式碼和截圖了,最終是在一個單例中發現了一個HashMap引用了一系列的Context在裡面。

好了,分析完畢,為了最小的改動,直接將HashMap修改成WeakHashMap,這個東西是在檢測到某個key值沒有被引用的情況下會回收掉entry,最後檢查一下它的get方法如果為空會不會有問題,看一遍沒有問題。

問題解決,雖然看起來分析的很愉快,但是在專案的關鍵時期大半夜看這個還是很傷的,開發者還是需要在寫程式碼的時候就注意記憶體洩露的問題,尤其是Context的使用,沒事多用Application的Context,實在不行也要注意及時主動置空和弱引用。

相關推薦

Android應用記憶體洩露分析、改善經驗總結

前言   通過這幾天對好幾個應用的記憶體洩露檢測和改善,效果明顯: 完全退出應用時,手動觸發GC,從原來佔有記憶體100多M降到低於20M; 手動觸發GC後,通過adb shell dumpsys meminfo packagename -d檢視Activity和View的數量也趨近於0了(沒有做到歸零

Android應用記憶體洩露分析以及優化方案

文章轉載http://blog.csdn.net/Soiol/article/details/52486871        本篇部落格是介紹Android記憶體優化方面的知識,在讀本篇部落格之前需要你熟練掌握Java 基礎知識(例如,靜態變數的生命週期,匿名內部類的使用,匿名物件等),並且具有一定的Andr

應用記憶體洩露問題分析例項

記憶體洩露,這個應用開發中比較容易出現的問題,由於短時間內難以測出來一般都比較難以發現,只能靠開發者的警覺性來避免,長時間的Monkey測試就成為一個可行的手段。 Monkey測試能給出一個直觀的記憶體變化曲線和日誌,GC日誌在記憶體緊張時都會打印出測試程序的記憶體資訊。往

應用記憶體洩露起因與解決方案分析

java gc機制 java記憶體管理與c/c++不同,java使用garbage collection機制,由虛擬機器管理記憶體。在大部分虛擬機器(包括android的ART)中,都採用了“可達性”分析演算法來進行記憶體管理。 原理是:選取某幾個root節

Android記憶體洩露分析

一,記憶體洩露 記憶體洩露:一個不在被使用的物件被另一個存活著的物件引用,在這種情況下垃圾回收器會跳過他,因為這種引用關係足以讓該物件駐留在記憶體中,記憶體洩露是在組織垃圾回收器為未來的記憶體分配提供空間,這些洩露的物件一直佔據著記憶體,導致我們的堆記憶體空間變得更小。也加劇了垃圾回

轉載:Android 記憶體洩露分析實戰演練

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://mp.csdn.net/postedit/82736058 轉載自任玉剛微信推文,非常全面所以記錄下來 1. 記憶體洩露簡介 記憶體洩露,即Memory Leak,指程式中不再使用到的物件因某種原因從而無法被GC正常回

記一次尷尬的Java應用記憶體洩露排查

這星期被線上JVM記憶體佔用不斷增大的問題所困擾,自己提出了一些假設,然後去實施驗證都一一失敗了,有一些經驗和教訓在這裡分享下. 之所以是尷尬,是最後因為偶爾出現修復了另一個問題導致記憶體不再上升,但這之間的關係還未明瞭,還需要繼續追蹤. 這裡講述一下這次排查的過程. 直接記憶體的錯誤判斷 伺服器的JVM配

補間動畫和屬性動畫記憶體洩露分析

在使用屬性動畫的時候,我們知道如果不在頁面結束的時候釋放掉動畫,就會引起記憶體洩露。 簡單的說就是ValueAnimator在AnimationHandler註冊自己的AnimationFrameCallback,AnimationFrameCallback介面

Android studio記憶體洩露分析工具使用

什麼是記憶體洩漏 Android虛擬機器的垃圾回收採用的是根搜尋演算法。GC會從根節點(GC Roots)開始對heap進行遍歷。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。而記憶體洩漏出現的原因就是存在了無

Handler記憶體洩露分析與解決方案

一、記憶體洩露分析 內部類會有一個指向外部類的引用。 垃圾回收機制中約定,當記憶體中的一個物件的引用計數為0時,將會被回收。 Handler 作為 Android 上的非同步訊息處理機制(好吧,我大多用來進行 worker thread 與 UI

ThreadLocal深入理解與記憶體洩露分析

ThreadLocal的介面方法 public T get() { } public void set(T value) { } public void remove() { } protected T initialValue() { } get()用來獲取

MemoryAnalyzer-記憶體洩露分析工具

概述 對於大型 JAVA 應用程式來說,再精細的測試也難以堵住所有的漏洞,即便我們在測試階段進行了大量卓有成效的工作,很多問題還是會在生產環境下暴露出來,並且很難在測試環境中進行重現。JVM 能夠記錄下問題發生時系統的部分執行狀態,並將其儲存在堆轉儲 (Heap Dump) 檔案中,從而為我們分析和診斷

Andriod-記憶體洩露-分析-解決方案

Activity 洩漏  我們第一個需要修復的問題就是 Activity 洩漏,我們先來看看記憶體洩漏是怎麼發生的。 Activity 洩漏通常是記憶體洩漏的一種。為什麼會洩漏呢?如果你持有一個未

Android記憶體洩露分析工具—Android Monitor

記憶體洩露大家應該不會陌生了,通常是因為該被釋放的物件被佔用,不能及時對其釋放,導致GC無法正常回收。我們可以使用一些工具來監控和分析導致記憶體洩露的位置和原因。用Eclipse的同志應該都知道MAT(Memory Analysis Tools),Android

Android記憶體洩露分析簡要思路

工作中遇到挺多需要分析記憶體洩露問題的情況,現在大致簡要寫下思路,等之後時間相對比較充裕再進行補充。 1.明白記憶體洩露的判斷依據? 個人總結為:持續增加,只增不減! 理解一下這8個字,配合幾個命令和工具來確定一下你的應用是否存在記憶體洩露問題,這是很關鍵的,如果一開始就判斷錯誤了

記憶體洩露分析工具VLD

Visual Leak Detector 下載,安裝。 把標頭檔案“include資料夾”放到工程原始碼路徑,並在需要檢查記憶體洩露的地方新增“include "vld.h" 在把庫vld.lib連線進去 注意,只能在DEBUG條件下才有用 這個工具還是

JAVA記憶體洩露分析和解決方案及WINDOWS自帶檢視工具

Java記憶體洩漏是每個Java程式設計師都會遇到的問題,程式在本地執行一切正常,可是佈署到遠端就會出現記憶體無限制的增長,最後系統癱瘓,那麼如何最快最好的檢測程式的穩定性,防止系統崩盤,作者用自已的親身經歷與各位分享解決這些問題的辦法.作為Internet最流行的程式語言之一,Java現正非常流行.我們的網

一個Vue頁面的記憶體洩露分析

什麼是記憶體洩露?記憶體洩露是指new了一塊記憶體,但無法被釋放或者被垃圾回收。new了一個物件之後,它申請佔用了一塊堆記憶體,當把這個物件指標置為null時或者離開作用域導致被銷燬,那麼這塊記憶體沒有人引用它了在JS裡面就會被自動垃圾回收。但是如果這個物件指標沒有被置為nu

Android Studio + MAT 給你看真實專案實戰的記憶體洩露分析

先貼出我要進行實戰的專案背景;專案已經出爐快半年時間了,現在要對它進行效能上的優化,這時候就要使用到 MAT 。然後隨便記錄一下我的分析歷程。 首先要了解兩個概念:記憶體溢位和記憶體洩漏 記憶體溢位

利用MAT進行記憶體洩露分析

前言 對於程式設計師來說碼程式碼容易,保證程式碼的穩定性很難。有時候寫完一個功能可能只需要一天時間,但是這個功能隱藏的bug導致的線上問題排查可能需要一週或者更長時間。因此,擁有良好的程式碼結構和編碼規範是一個程式設計師應該長期堅持併為之奮鬥的一