前言
我在干活过程中需要实时获取Android中system_server
进程的内存信息。而在Android 10上实现对特定进程的内存监控时踩了几个坑,因此在此记录一下几个坑点和解决方案。
Android获取内存信息的几种方式
参考文献1中给出了几种获取内存信息的方式:
使用
ActivityManager
的getMemoryInfo(ActivityManager.MemoryInfo outInfo)
使用
ActivityManager
的MemoryInfo[] getProcessMemoryInfo(int[] pids)
使用
Debug
的getMemoryInfo(Debug.MemoryInfo memoryInfo)
以及getNativeHeapSize ()
、getNativeHeapAllocatedSize ()、getNativeHeapFreeSize ()
使用
dumpsys meminfo
命令使用
adb shell procrank
命令使用
adb shell cat /proc/meminfo
命令
在上述的几种方式中前4种可以获取到某一进程的详细内存信息,第5种方法可以获取到进程的内存总量相关的信息(Vss, Rss, Pss, Uss)而第6种方式只能获取系统的总体内存状态。由于我在干活时希望能够获取到系统进程的详细内存信息,并且因此仅考虑前4种方式。同时如果使用第4种方式,需要经过多次输出的解析,会带来额外的开销。
坑点
- 坑点1: Android10中方式1、2获取内存信息的采样率是5分钟,无法实时获取
- 坑点2: Android 10中普通应用程序仅能获取本进程的内存信息。
- 坑点3: 实时获取应用内存信息具有很大时间开销。
解决方案
- 对于坑点1,使用
Debug
的getMemoryInfo(Debug.MemoryInfo memoryInfo)
方法获取进程的内存信息,方式4底层也是通过调用该方法获取应用内存信息的,对dumpsys meminfo
的分析见参考文献2-4。 - 对于坑点2,使用
xposed
插桩需要获取内存信息的目标应用,在其中注册一个BroadcastReceiver
,并启动一个Service
用于数据交换。当用户程序需要获取目标应用的内存信息时,只需要通过Service
发送一个广播请求,目标应用注册的BroadcastReceiver
接收广播后调用Debug.getMemoryInfo(Debug.MemoryInfo memoryInfo)
方法获取目标应用的内存信息,将该内存信息保存到Service
中,进一步发送给用户程序。通过这样一个过程普通用户程序就可以获取到系统进程的内存信息。 - 对于坑点3,只能通过降低API的调用频率,或者仅获取部分内存信息(如仅获取PSS)来缓解。