解析Android内存分析的指标

在 Android 系统开发中,为了精准衡量进程的内存消耗,通常会使用 VSS、RSS、PSS、USS 这四个指标。由于内存共享机制的存在,单一的"内存占用"数字往往无法真实反映进程对系统的影响,因此这四个指标提供了不同维度的观察视角。

0x00 核心含义详解

我们可以通过一个简单的模型来理解:假设进程 A 使用了 50MB 私有内存 ,并与进程 B 共享一个 20MB 的动态库。

VSS (Virtual Set Size) - 虚拟耗用内存

  • 含义:进程能访问到的全部虚拟地址空间大小。
  • 包含:已分配但未实际使用的内存、映射到磁盘的文件、共享库占用的全部空间等。
  • 特点 :数值最大。它不代表真实的物理内存消耗,对于性能分析意义较小。

RSS (Resident Set Size) - 实际使用物理内存

  • 含义:进程当前实际占用的物理内存(RAM)。
  • 包含 :进程的私有内存 + 共享库的全部大小。
  • 缺点:存在"重复计算"。如果有 10 个进程都用了那个 20MB 的共享库,每个进程的 RSS 都会计入这 20MB。将所有进程的 RSS 相加,会远大于系统总内存。

PSS (Proportional Set Size) - 比例分配内存

  • 含义 :将共享库的大小按共享进程的数量均摊。
  • 计算:私有内存 + (共享库大小 / 共享该库的进程数)。
  • 优点 :最客观的指标。如果将系统中所有进程的 PSS 相加,结果几乎等于系统实际消耗的总内存。它是衡量进程系统级负担的最佳标准。

USS (Unique Set Size) - 进程独占内存(最常用)

  • 含义:进程完全独占的物理内存。
  • 包含:只有该进程能访问到的 RAM 区域。
  • 优点 :分析内存泄露的核心指标。它表示如果杀死该进程,系统能立刻回收的内存量。

0x01 核心判断标准:为什么 USS 是"金标准"?

在分析泄漏时,我们通常遵循这个优先级:USS > PSS > RSS > VSS。

  • VSS 和 RSS 的局限性:由于 RSS 包含了共享库内存,当系统其他进程加载或卸载共享库时,你的进程 RSS 可能会波动,这会产生"伪泄漏"的干扰。
  • PSS 的参考意义:PSS 能够反映你的进程对系统总内存的真实贡献。如果 PSS 持续上涨,说明你的应用正在拖慢系统。
  • USS 的决定性作用 :USS 只包含进程完全独占的内存。 内存泄漏本质上是进程内部的对象无法被回收,因此内存泄漏一定会直接反映在 USS 的上涨上。

0x02 分析内存泄漏分析的流程

第一步:建立基准线 (Baseline)

在应用启动并进入主界面稳定后,记录当前的内存状态。

shell 复制代码
adb shell dumpsys meminfo <your_package_name>

重点记录:TOTAL Pss 和 Private Dirty(后者非常接近 USS)。

第二步:执行重复性操作 (Stress Test)

内存泄漏通常发生在 Activity 销毁或长生命周期对象(如 Singleton、Thread)中。执行以下操作:

  1. 进入一个怀疑有泄漏的页面,再退出。
  2. 重复上述过程 10 次以上。
  3. 手动触发几次 GC(在 Android Studio Profiler 中点击小垃圾桶图标,或通过 adb shell cmd activity gc)。

第三步:对比观测

再次运行 adb shell dumpsys meminfo <your_package_name>,观察数据变化:

  • 如果 USS (Private Dirty) 阶梯式上升 :说明存在私有内存泄漏(通常是 Java 对象、Bitmap 或 Native 堆内存)。
  • 如果 PSS 上升但 USS 稳定:这种情况极少见,可能意味着你调用的系统共享资源(如某些系统服务的缓存)在增加,而不是你进程内部的泄漏。
  • 如果 PSS/USS 均不增加,但 VSS 疯狂增长:说明你在不断地申请虚拟地址空间(例如创建了大量线程,每个线程占用 1MB 虚拟栈空间,但实际还没开始使用物理内存)。
shell 复制代码
Applications Memory Usage (in Kilobytes):
Uptime: 102275 Realtime: 102275

** MEMINFO in pid 3069 [com.android.launcher3] **
                   Pss  Private  Private     Swap      Rss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty    Total     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------   ------
  Native Heap    11128    11060        0        0    13796    19812    13511     2600
  Dalvik Heap     2316     2188        0        0     6620    27729     3153    24576
 Dalvik Other     2587     2264        0        0     3528                           
        Stack      736      736        0        0      740                           
       Ashmem        2        0        0        0        8                           
      Gfx dev     1244     1244        0        0     1244                           
    Other dev       36        0       36        0      284                           
     .so mmap     6076      212      128        0    54512                           
    .jar mmap     1922        0        0        0    26648                           
    .apk mmap    14824        0    13900        0    38756                           
    .ttf mmap       54        0        0        0      228                           
    .dex mmap      213        4        0        0      504                           
    .oat mmap       55        0        0        0     2044                           
    .art mmap     7794     7404        4        0    20040                           
   Other mmap     1179        4       32        0     4984                           
   EGL mtrack    40288    40288        0        0    40288                           
    GL mtrack     6104     6104        0        0     6104                           
      Unknown      466      448        0        0     1100                           
        TOTAL    97024    71956    14100        0    97024    47541    16664    27176
 
 App Summary
                       Pss(KB)                        Rss(KB)
                        ------                         ------
           Java Heap:     9596                          26660
         Native Heap:    11060                          13796
                Code:    14256                         123424
               Stack:      736                            740
            Graphics:    47636                          47636
       Private Other:     2772
              System:    10968
             Unknown:                                    9172
 
           TOTAL PSS:    97024            TOTAL RSS:   221428      TOTAL SWAP (KB):        0
 
...

0x03 针对不同类型的泄漏分析

A. Java 层泄漏 (Activity/Fragment)

  • 现象 :TOTAL Pss 和 Java Heap 持续增长。

  • 分析 :查看 dumpsys meminfo 最后的 Objects 部分。

    • Views 和 Activities 的数量。如果你退出了页面,Activities 数量没有减少,那就是典型的 Activity 泄漏。

B. Native 层泄漏 (C++/JNI)

  • 现象 :Native Heap 指标持续增长,且 USS 同步上涨。
  • 分析 :如果你在 JNI 中使用了 malloc 或 new 但没有 free,这部分内存会体现在 Native Heap 中。

C. 共享内存/文件描述符泄漏 (SharedMemory/FD)

如果 SharedMemory 没有被正确关闭:

  • 现象 :USS 可能不会显著增长(如果你已经 munmap 了),但文件描述符 (FD) 会耗尽。

  • 检查方式:

    bash 复制代码
    adb shell ls -l /proc/<pid>/fd | wc -l

    例如检查3069号进程(com.android.launcher3)

    shell 复制代码
    adb root
    adb shell ls -l /proc/3069/fd | wc -l
    
    # 输出
    # 82

    重复操作后,如果 FD 数量不断增加,说明你的 SharedMemory 或 ParcelFileDescriptor 没有执行 close()。

0x04 自动化检测工具推荐

虽然手动分析 dumpsys 很有帮助,但在实际开发中,建议配合以下工具:

工具 优势
LeakCanary 自动化程度最高,直接在手机端弹窗告知 Java 泄漏引用链。
Android Studio Profiler 可视化实时查看 PSS 分布,支持 Capture Heap Dump 分析堆快照。
Perfetto / Systrace 适合分析 Native 层和系统级的内存分配行为。
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui