為了更深入的分析,你可能想去通過adb命令研究你的應用的內存在不同的RAM分配間是怎么划分的.
常用adb命令就是如下兩個:
- adb shell dumpsys meminfo | grep 進程名
- adb shell dumpsys meminfo <package_name|pid> [-d]
-d:打印更多的和Dalvik及ART內存使用的相關信息
輸出信息列出了你的應用的內存當前分配,以KB為單位。
那么內存打印出來那么多數據,應該重點關注哪些信息呢?
Private (Clean and Dirty) RAM
這只是你的進程正在使用的內存。 這是當您的應用程序的進程被銷毀時系統可以回收的大部分RAM。 一般來說,最重要的部分是private dirty RAM,這是最昂貴的,因為它僅由您的進程使用,其內容僅存在於RAM中,因此無法分頁到存儲(因為Android不使用交換)。 您所做的所有Dalvik和本機堆分配將是private dirty RAM; 您與Zygote進程共享的Dalvik和本機分配是shared dirty RAM。
Proportional Set Size (PSS)
這是您的應用程序的RAM使用量的衡量標准,它考慮到跨進程共享頁面。 任何對您的過程唯一的RAM頁面直接有助於其PSS值,而與其他進程共享的頁面僅與共享的數量成比例地貢獻PSS值。 例如,兩個進程之間共享的頁面將為每個進程的PSS貢獻一半的大小。
PSS測量的一個很好的特點是您可以將所有進程的PSS相加,以確定所有進程正在使用的實際內存。 這意味着PSS對於進程的實際RAM權重和與其他進程的RAM使用以及總可用RAM進行比較是一個很好的衡量標准。
補充知識點:
http://www.cnblogs.com/JianXu/p/5685217.html
關於VSS、RSS、PSS、USS的理解,這篇博客寫得很清楚。
例如,以下是OPPO R7設備上查看花椒客戶端進程的輸出。
adb shell dumpsys meminfo com.huajiao
重點關注如下幾個字段:
(1) Native/Dalvik 的 Heap 信息中的alloc
具體在上面的第一行和第二行,它分別給出的是JNI層和Java層的內存分配情況,如果發現這個值一直增長,則代表程序可能出現了內存泄漏。
(2) Total 的 PSS 信息
這個值就是你的應用真正占據的內存大小,通過這個信息,你可以輕松判別手機中哪些程序占內存比較大了。
(3)一般來說,只關心Pss Total和Private Dirty列。 在某些情況下,“private clean”和“heap”分配列還提供了有趣的數據。
有關不同內存分配(行)的更多信息如下:
Dalvik Heap
在您的應用程序中使用Dalvik分配的RAM。 Pss Total包括所有的合並分配(通過它們在進程之間的共享來加權,如上面的PSS定義所述)。 Private dirty的數字是實際的RAM,只承諾您的應用程序的堆,由您自己的配置和任何Zygote分配頁面,由於從Zygote從您的應用程序的進程自從修改。
(Zygote:一個特殊的虛擬機進程,它是機實例的孵化器。它在系統啟動的時候就會產生,它會完成虛擬機的初始化,庫的加載,預制類庫和初始化的操作。
如果系統需要一個新的虛擬機實例,它會迅速復制自身,以最快的訴據提供給系統。對於一些只讀的系統庫,所有虛擬機實例都和Zygote共享一塊內存區域。)
注意:在具有Dalvik其他部分的較新平台版本中,Dalvik堆的Pss Total和Private Dirty數字不包括Dalvik開銷,如即時編譯(JIT)和GC記帳,而舊版本將其全部合並Dalvik。
Heap Alloc堆分配是Dalvik和本機堆分配器為您的應用程序跟蹤的內存量。 這個值大於Pss Total和Private Dirty,因為你的進程是從Zygote分派的,它包括你的進程與所有其他人共享的分配.
.so mmap 和 .dex mmap
RAM用於映射的.so(本機)和.dex(Dalvik或ART)代碼。 Pss總數包括跨應用程序共享的平台代碼; private clean是您的應用程序自己的代碼。 一般來說,實際的映射大小會更大 - 這里的RAM只是當前由應用程序執行的代碼所需要的內存。 但是,.so mmap有一個很大的private dirty,這是由於在加載到最終地址時修復本地代碼。
.oat mmap
這是基於多個應用程序通常使用的預加載類的代碼映像所使用的RAM量。 此圖像在所有應用程序之間共享,不受特定應用程序的影響。
.art mmap
這是基於多個應用程序通常使用的預加載類的堆映像使用的RAM量。 此圖像在所有應用程序之間共享,不受特定應用程序的影響。 即使ART圖像包含對象實例,也不計入堆大小。
.Heap (only with -d flag)
這是您的應用程序的堆內存量。 這不包括圖像和大對象空間中的對象,而是包含合適的空間和非移動空間。
.LOS (only with -d flag)
這是ART大型對象空間使用的RAM量。 這包括合子大對象。 大對象都是大於12KB的原始數組分配。
.GC (only with -d flag)
這是您的應用程序的內部GC會計開銷的金額。 沒有任何辦法減少這種開銷。
.JITCache (only with -d flag)
這是JIT數據和代碼高速緩存使用的內存量。 通常,這是零,因為所有的應用程序將在安裝時被編譯。
.Zygote (only with -d flag)
這是Zygote空間使用的內存量。 合子空間是在設備啟動期間創建的,不會被分配。
.NonMoving (only with -d flag)
這是ART非移動空間使用的RAM量。 非移動空間包含特殊的不可移動對象,如字段和方法。 您可以通過在應用程序中使用較少的字段和方法來減少此部分。
.IndirectRef (only with -d flag)
這是ART間接參考表使用的RAM量。 通常這個數量很小,但是如果它太高,可以通過減少使用的本地和全局JNI引用來減少它。
Unknown
任何RAM頁面,系統無法分類到其他更具體的項目之一。 目前,這主要包含本地分配,由於地址空間布局隨機化(ASLR),收集這些數據時工具無法識別。 像Dalvik堆,Pss Total for Unknown考慮到與Zygote的共享,Private Dirty是僅供您應用使用的未知RAM。
TOTAL
您的流程使用的PSS(總比例集大小)RAM。 這是它上面的所有PSS字段的總和。 它表示您的進程的總體內存權重,可以直接與其他進程和總可用內存進行比較。
Private Dirty和Private Clean是您進程中的總分配,不與其他進程共享。 一起(特別是private dirty),這是當你的進程被銷毀時將釋放回系統的RAM量。 Dirty Ram是已修改的頁面,因此必須保留到RAM中(因為沒有交換);Clean RAM是已經從持久性文件映射的頁面(例如正在執行的代碼),因此如果不使用一段時間,則可以進行分頁。
ViewRootImpl
在您的進程中活動的根視圖數。 每個根視圖與一個窗口相關聯,因此這可以幫助您識別涉及對話框或其他窗口的內存泄漏。
AppContexts and Activities
當前存在於您的進程中的應用程序上下文和活動對象的數量。 這可以幫助您快速識別由於靜態引用而無法收集的泄漏的Activity對象,這是常見的。 這些對象通常具有與它們相關聯的許多其他分配,這使得它們成為跟蹤大內存泄漏的好方法。
補充其他參數(列)含義:
Naitve Heap Size: 從mallinfo usmblks獲得,代表最大總共分配空間
Native Heap Alloc: 從mallinfo uorblks獲得,總共分配空間
Native Heap Free: 從mallinfo fordblks獲得,代表總共剩余空間
Native Heap Size 約等於Native Heap Alloc + Native Heap Free
mallinfo是一個C庫, mallinfo 函數提供了各種各樣的通過C的malloc()函數分配的內存的統計信息。
Dalvik Heap Size:從Runtime totalMemory()獲得,Dalvik Heap總共的內存大小。
Dalvik Heap Alloc: Runtime totalMemory()-freeMemory() ,Dalvik Heap分配的內存大小。
Dalvik Heap Free:從Runtime freeMemory()獲得,Dalvik Heap剩余的內存大小。
Dalvik Heap Size 約等於Dalvik HeapAlloc + Dalvik Heap Free