不冻结 APP 的 dump hprof
在 LeakCanary 浅析 和 Matrix - ResourcesCanary 浅析 这两篇文章里,介绍了检测内存泄漏的两种相似的思路:
但无论 LeakCanary 还是 Matrix.ResourcesCanary 都没有解决 dump hprof 时整个 APP 被「冻结」的问题,而一次 dump hprof 往往要持续 10s 甚至更多,这在线上环境下是不可接受的,所以在发生内存泄漏后只能上报类信息,开发者收到后人工检查涉及此类的相关代码找出泄漏点。但是这种方式是极其低效和不准确的,如果能在端侧找出泄漏对象的 GC ROOT PATH,就能极大地减少人工量,并且提高后续修复的准确度。
如果能够在不冻结 APP 的情况下 dump hprof,不仅仅能够上报内存泄漏问题,还能对 OOM 进行预警:比如监控 JVM 的内存使用率,当达到 90% 的时候将 hprof 上报分析
KOOM 提出了一个在不冻结 APP 的情况下 dump hprof 的思路:fork 出子进程,总体流程是这样的:
整个过程 APP 只在 fork 前后冻结了一小会,这么短的时间是可以接受的,由于 fork 采用 Copy-On-Write 机制,子进程能够继承父进程的内存
暂停和恢复 JVM
SuspendVMEv 和 ResumeVMEvScopedSuspendAll(局部变量,构造函数暂停 JVM,析构函数恢复 JVM)KOOM 不支持但是要从各个 Android 版本的 so 文件里准确找到这些函数(符号)是有难度的,寻找 SuspendVMEv 和 ResumeVMEv 的地址代码如下