- RAM:最快的内存类型
- zRAM:用于交换空间的RAM分区,数据进入zRAM会压缩,减小内存占用,从zRAM出来时会解压
- Storage:持久化数据存储
https://developer.android.com/topic/performance/memory-management
内存页面
- 缓存页:有Storage中的文件(代码或内存映射文件)
- 私有页:一个进程拥有且不能共享
- Clean:在Storage中未修改的文件副本,可由kswapd 删除增加可用内存
- Dirty:在Storage中有文件副本,但是经过了修改,可有kswapd移动到zRAM中压缩以减小内存占用,增加可用内存
- 共享页:多个进程使用
- Clean:在Storage中有未修改的文件副本,可由kswapd删除增加可用内存
- Dirty:在Storage中有文件副本,但是经过了修改,可由kswapd调用msync()活着munmap()写回Storage中,释放内存,增大可用内存 ()
- 私有页:一个进程拥有且不能共享
- 匿名页:Storage中没有对用的文件副本(代码运行时初始化的一些数据)
- Dirty:可有kswapd移动到zRAM中压缩,减小内存占用,增大可用内存
Tip:Clean Page 因为在Storage中有持久化的缓存,所以内存回收时可以直接删除
内存不足管理
内存不足时会调用 onTrimMemory 通知应用内存不足
- 内核交换守护进程 (kswapd),即上述内存页面中的kswapd对内存的管理
- 低内存终止守护进程(LMK),使用oom_adj_score的分值来确定正在运行的进程优先级,来决定终止哪个进程。
评分由高到低进行kill
- Background apps 后台应用
- Previous app 上一个应用
- Home app 主屏幕应用,启动器应用。??????
- Services
- Perceptible apps 可觉察的应用,例如:键盘,桌面组件等
- Foreground app 前台应用
- Persistent 持久性 属于系统
- System 系统进程
- Native 例如kswapd(内核交换守护进程)
计算内存占用量
- RSS:非共享内存页面数量+共享内存页面数量
- PSS:非共享页面数量+ 共享内存/process num的页面数量
- USS:非共享的页面数量
从上看PSS在计算内存占用时,共享内存需要花费时间计算页面数量,而RSS不区分共享和非共享页面数量,所以更适合跟踪内存分配量变化。
JAVA 虚拟机内存问题
- Runtime.getRuntime().maxMemory() 虚拟机可用的最大内存
- Runtime.getRuntime().totalMemory() 虚拟机已申请使用的内存
- Runtime.getRuntime().freeMemory() 虚拟机申请了未使用的内存
- 可用内存 = maxMemory - (totalMemory-freeMemory)// largeheap=”true” 可以让虚拟机内存增大
1
2
3
4
5
6maxMemory:201326592=192MB
totalMemory:9466560
freeMemory:6067952
usedMemory:9466560-6067952= 3398608 = 3318.953125 = 3.24MB
availMemory = 201326592 - 3398608 = 188.7MB
pixel 4xl aosp android 10 | 小米10 Ultra | |
---|---|---|
largeheap=”false” | 192MB | 256MB |
largeheap=”true” | 512MB | 512MB |
Android内存大小
ActivityManager.MemoryInfo
- lowMemory 是否低内存
- availMem 可用内存
- totalMem 总内存
- threshold 阈值
1
2
3
4
5
6
7ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryInfo(memoryInfo);
boolean lowMemory = memoryInfo.lowMemory;
long availMem = memoryInfo.availMem;
long totalMem = memoryInfo.totalMem;
long threshold = memoryInfo.threshold;当前进程内存
1
2
3
4
5
6
7
8
9summary.code,21164 // apk,dex,jar,so,ttf,oat等
summary.stack,80 // java栈 和 native栈
summary.graphics,536 // 图形相关 私有Gfx, EGL和GL
summary.java-heap,3192=3.24MB // java堆// 和上面usedMemory是一样的
summary.native-heap,7584 // c++堆
summary.system,6827 // 系统内存,包括共享内存
summary.total-pss,46955 // 虚拟机,native,other,swap
summary.private-other,7572 // 私有的clean+dirty - 虚拟机,native,code,stack,graphics
summary.total-swap,5608 // 非pss swap
1 | Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); |