一、Android内存管理模型
Art(Android RunTime)虚拟机和Dalvik虚拟机都是以分页机制paging和内存映射机制(memory-mapping, mmapping)来管理内存。 The Android Runtime (ART) and Dalvik virtual machine use paging and memory-mapping (mmapping) to manage memory. This means that any memory an app modifies—whether by allocating new objects or touching mmapped pages—remains resident in RAM and cannot be paged out. The only way to release memory from an app is to release object references that the app holds, making the memory available to the garbage collector. That is with one exception: any files mmapped in without modification, such as code, can be paged out of RAM if the system wants to use that memory elsewhere.
二、如何查询App的内存占用情况
- 使用dumpsys命令
dumpsys meminfo PackageName
//or dumpsys meminfo pid
复制代码
查询结果如下所示:
NOTE: 下面的内存信息可能随着Android版本的不同而有不同的表示形式
/** MEMINFO in pid 18227 [com.google.android.apps.maps] **/
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 10468 10408 0 0 20480 14462 6017
Dalvik Heap 34340 33816 0 0 62436 53883 8553
Dalvik Other 972 972 0 0
Stack 1144 1144 0 0
Gfx dev 35300 35300 0 0
Other dev 5 0 4 0
.so mmap 1943 504 188 0
.apk mmap 598 0 136 0
.ttf mmap 134 0 68 0
.dex mmap 3908 0 3904 0
.oat mmap 1344 0 56 0
.art mmap 2037 1784 28 0
Other mmap 30 4 0 0
EGL mtrack 73072 73072 0 0
GL mtrack 51044 51044 0 0
Unknown 185 184 0 0
TOTAL 216524 208232 4384 0 82916 68345 14570
复制代码
Here is an older dumpsys on Dalvik of the gmail app:
** MEMINFO in pid 9953 [com.google.android.gm] **
Pss Pss Shared Private Shared Private Heap Heap Heap
Total Clean Dirty Dirty Clean Clean Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------ ------
Native Heap 0 0 0 0 0 0 7800 7637(6) 126
Dalvik Heap 5110(3) 0 4136 4988(3) 0 0 9168 8958(6) 210
Dalvik Other 2850 0 2684 2772 0 0
Stack 36 0 8 36 0 0
Cursor 136 0 0 136 0 0
Ashmem 12 0 28 0 0 0
Other dev 380 0 24 376 0 4
.so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5)
.apk mmap 235 32 0 0 1252 32
.ttf mmap 36 12 0 0 88 12
.dex mmap 3019(5) 2148 0 0 8936 2148(5)
Other mmap 107 0 8 8 324 68
Unknown 6994(4) 0 252 6992(4) 0 0
TOTAL 24358(1) 4188 9724 17972(2)16388 4260(2)16968 16595 336
Objects
Views: 426 ViewRootImpl: 3(8)
AppContexts: 6(7) Activities: 2(7)
Assets: 2 AssetManagers: 2
Local Binders: 64 Proxy Binders: 34
Death Recipients: 0
OpenSSL Sockets: 1
SQL
MEMORY_USED: 1739
PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62
复制代码
1. 各列字段的含义
1.1 Private (clean and dirty) RAM
该内存区域为App进程私有部分。App关闭之后,该部分的内存被释放。通常而言,Private Dirty RAM是最为重要的,因为该部分所有的内容都只处于RAM中,不会使用分页机制将其map到硬盘。Private Dirty RAM包含,所有在App内部(也就是说不包含系统创建的)所创建的Native Heap和Dalvik Heap。而与Zygote进程共享的内存区域为Shared/Swapped Dirty RAM。
Dirty与clean的区别:clean即干净数据,指该区域的数据与硬盘数据一致,不需要回写即可回收该区域内存。而Dirty正好相反,指脏数据,要回收该区域,必须先回写到硬盘。
1.2 Proportional Set Size (PSS)
PSS指App实际占用的物理内存大小,除了Private RAM之外,还包括与其他进程共享的内存区域(在Android都是以page为单位来分配内存的,通常page size为4KB)。注意,在计量与其他进程共享的内存大小时,是平均分配的。$$PSS = Private RAM + Shared Dirty RAM ➗ 共享进程数$$ 当进程死亡之后,其他进程的PSS就会变大,所以我们可以通过创建新的进程来缓解内存压力。
1.3 Heap Size
1.4 Heap Alloc
1.5 Heap Free
2. 各行字段的含义
2.1 Native Heap
本地堆
2.2 Dalvik Heap
Java 虚拟机堆
2.3 Dalvik Other: 包括LinearAlloc, Accounting, Code_cache
LinearAlloc: JVM存储载入类的方法信息的区域。 Accounting: 包括dalvik-aux-structure, dalvik-bitmap, dalvik-card-table。主要用作标记和指针表。 Code_Cache: 包括dalvik-jit-code-cache。jit编译代码后的缓存
2.4 Stack
栈区域
2.5 Ashmen: Anonymous Shared Memory, 匿名共享内存
以驱动的形式,存储于内核中。有两个功能,一是辅助内存管理系统来管理不再使用的内存块。二是利用Binder通讯机制来实现进程间内存共享。
2.6 mmap: memory Map
mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系
Cow: Copy-On-Write
fork()会产生一个和父进程完全相同的子进程。 Linux写时拷贝技术(copy-on-write)
基于Ashmen和Cow,android最明显的特征就是与Zygote进程共享内存。为了加快启动速度及节约内存,Android应用的进程都是由Zygote进程fork出来的。由于Zygote进程已经载入了完整的Dalvik虚拟机和Android应用框架代码,fork出来的进程与Zygote进程共享同一块内存,这样就节约了每个进程单独载入的时间和内存。应用进程只需要载入自己的Dalvik字节码和资源即可开始工作。
所以,Android应用进程包含以下几部分
OOM的分类
Tools for analyzing RAM usage
DDMS
Android性能优化典范
Investigating Your RAM Usage Investigating Your RAM Usage总结:
- 学会查看Log中关于GC的信息,注意Art和Dalvik打印出的GC类别的不同。
- 学会使用Android-Monitor之DDMS,学会生成、转换及分析hprof
- adb shell dumpsys meminfo <package_name|pid> [-d] Manage Your App's Memory