废话不说,直接上干货。
代码中使用 Debug 的 getMemoryInfo(Debug.MemoryInfo memoryInfo) 或 ActivityManager 的 MemoryInfo[] getProcessMemoryInfo(int[] pids)
- ActivityManager mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- Debug.MemoryInfo[] memoryInfoArray = mAm.getProcessMemoryInfo(pids);
MemoryInfo 对象中可以看看详细的内存信息,字段如下: 目前很多内存测试工具都是采用这种方式,如哆啦 A 梦、GT 等。这种方式简单方便
- adb shell dumpsys meminfo package_name | pid
一般关注关 PSS 列的这几个字段:
一般公司测试都是会采用这种方式获取内存数据的
Linux 在 2.6 版本之后有一个 proc 伪文件,在它下面记录各种信息,其中在 proc/pid/smaps 记录某个 pid 的内,smaps 记录内存详细的使用情况。使用下面的命令可以读文件的值
- cat / proc / pid / smaps
文件格式如下:
文件字段意义:
smaps 文件一般有啥作用呢,譬如我们通过 dumpsys meminfo 获取内存时,发现某一项内存数据异常,想弄清楚数据都是有哪些文件产生,我们就可以通过读取 smaps 详细排查。
我们执行 dumpsys memInfo 命令后的代码执行流程是怎样的呢,dumpsys 命令会根据传进来的参数通过函数 checkService 来找到具体的 service, 然后执行该 service 的 dump 方法,最总达到 dump service 的目的。
那我们传进入的 memInfo 对应的是哪个 service 呢,这个我们需要查看 ActivityManagerService.Java 类,搜索一下 memInfo,最后我们发现它对应的 service 是 MemBinder。
我们点击 MemBinder 类看类内部的实现
方法内部首先会进行 android.Manifest.permission.DUMP 权限检查,最终调用 dumpApplicationMemoryUsage 方法,我们再看 dumpApplicationMemoryUsage 方法做了哪些操作
这个方法内容比较多,这里我们只显示了它最终调的地方,我们最终发现最后会调用 android.os.Debug.java 类。
其实会调用 android.os.Debug.java 类调用了大量的 Native 方法实现的,android.os.Debug.java 对应的 native 文件是 android_os_Debug.cpp,上面的 Debug.getMemoryInfo(pid, mi) 实际上最后调用了 android_os_Debug.cpp 的 android_os_Debug_getDirtyPagesPid 方法
android_os_Debug_getDirtyPagesPid 方法调用了 load_maps(int pid, stats_t* stats) 方法
load_maps 中是通过读取 smaps 文件内容,到此 dumpsys memInfo 的实现就非常清晰了。
第一种代码的实现方式,其实最后走的流程和上面的是一样的。
android_os_Debug.cpp 地址: android_os_Debug.cpp 文件
1. 内存是否持续上涨:进入某项功能内存增长,退出功能时内存是否下降
2. 是否频繁的 GC:频繁的 gc 可能是因为你的程序内存碎片导致的,这也是需要优化的一个方向
3. 内存的峰值是否在单个应用允许的最大值之内
来源: https://juejin.im/post/5a3cc4416fb9a0450d11453e