为了更深入的分析,你可能想去通过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