Android native内存分配2.0-private dirty memory不回收

本文探讨了C++中使用malloc进行内存分配的场景,特别是在Android平台上读取模型文件后的内存释放问题。观察到释放内存后,虽然Heap Size有所减少,但Private Dirty并未下降,导致实际内存占用不变。文章还分析了手机屏幕亮灭对脏页回收的影响,以及不同进程状态下的系统回收策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Context

情景:
  1. 在C++中用 malloc申请内存
  2. 用申请的内存读取 模型文件
  3. 释放内存,AndroidStudio的Profiler显示内存大小不变
分析工具
  1. adb shell dumpsys meminfo com.albertsnow.graphicdemo分析
  2. Android Studio的profiler功能
输出形式
//仅用于数据名称演示,非本case的实际dump信息
                   Pss  Private  Private     Swap     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap        0        0        0        0    12288     9963     2324
  Dalvik Heap        0        0        0        0     4952     2971     1981
        TOTAL        0        0        0        0    17240    12934     4305
         Native Heap:        0
               TOTAL:        0      TOTAL SWAP (KB):        0
观察结果:

malloc内存分配在Private dirty部分,release后 Heap size已经下降,但是Private Dirty并没有下降。导致进程dump出的实际占用 内存不变

额外的实验现象:
  1. 手机亮灭屏后,dirty内存会被回收
  2. 该加载逻辑在Service中,Service在独立于应用包名进程的单独进程中。但将该逻辑移到主进程中,dirty也会被回收
推测:

是系统对不同的进程状态,有不同的回收策略

代码解决:
 mmap(NULL, chunck_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

代替malloc。原理 StackOverFlow link

进程memory Private & Public

进程共享的内存(Android的SDK代码)为public。进程独享的为private

进程clean dirty

进程的虚拟内存以page(页,大小4K)为最小大小,加载于内存中。并且在disk的swap(交换)区备份,如果两方不一致(memory的更改,还没来得及写入swap)

举例:
  1. 进程A加载于内存中(分为2个page)
  2. 用户启动进程B,但内存只有2个page(也就是8K),但已经被A进程占用。
  3. 系统就会吧 进程A swap到磁盘上,空出的2个page给B进程用。
    所以 memory与disk内存书写不一致,就是dirty memory。

而无法立即回收,更改Exel,在原来基础上写了很多。等到退出Exel(release)时,提醒文件已经被更改(memory is dirty)无法关闭(release)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值