1.4.3 zygote共享内存机制
上一小节介绍了应用各部分内存的含义,读者对dumpsys meminfo输出的大部分数据都能够有所理解。但dumpsys meminfo工具还会输出Heap Size/Alloc/Free部分的数值。我们知道这些数值是Dalvik虚拟机统计的内存堆的使用量,但这些数值是如何对应到Pss内存上的?比如Heap Alloc和Heap Pss往往相差不远,那是不是可将其看做基本等同的呢?下面我们试图解释这几项数值之间的关系。
由于虚拟机运行时并不区分某个对象实例是Android框架共享的还是应用独有的,Heap Alloc统计的是由虚拟机分配的所有应用实例的内存,所以会将应用从zygote共享的部分也算进去,于是Heap Alloc值总是比实际物理内存使用值要大。
Heap Alloc虽然反映了Java代码分配的内存,但存在框架造成的失真。除此之外,进程还有许多其他部分也需要使用内存。为了准确了解应用消耗的内存,我们要从进程角度而不是虚拟机角度来进行观察。
Pss表示进程实际使用的物理内存,是由私有内存加上按比例分担计算的各进程共享内存得到的值。例如,如果有三个进程都使用了一个消耗30KB内存的so库,那么每个进程在计算这部分Pss值的时候,只会计算10KB。总的计算公式是:
Dalvik Pss内存 = 私有内存Private Dirty
+ (共享内存Shared Dirty / 共享的进程数)
从实际含义来讲,Private Dirty部分存放的是应用新建(new)出来的对象实例,是每个应用所独有的,不会再共享。Shared Dirty部分主要是zygote加载的Android框架部分,会被所有Android应用进程共享。通常进程数的值在10~50的范围内。
Pss是一个非常有用的数值,如果系统中所有进程的Pss相加,所得和即为系统占用内存的总和。但要注意的是,进程的Pss并不代表进程结束后系统能够回收的内存大小。