KOOM 学习计划
目标:不只是"看懂代码",而是理解每个设计决策背后的 why,能够向别人讲清楚原理,并具备排查线上内存问题的判断力。 建议周期:4 周,每周投入 5-8 小时(可根据自己节奏拉长或压缩)
预备知识自查(开始前先确认)
在正式进入 KOOM 之前,确认自己对下面几个基础概念不陌生,不然会在细节里卡住:
- JVM/ART 的 GC Roots、可达性分析基本原理
- Linux 进程
fork()的行为,以及 Copy-on-Write(写时复制)机制 - Android 进程模型(一个 App 可以有多进程,进程间内存不共享)
- JNI 基础(Java 层与 Native 层如何互相调用)
- 什么是 hprof 文件格式(Java Heap Dump 的标准格式)
如果某一项完全陌生,先花 30 分钟补一下概念,不需要精通,有个印象即可,后面遇到会随时补充。
第 1 周:Java Heap 泄漏监控(koom-java-leak)
为什么先学这个:三个模块里技术栈最贴近日常 Java/Kotlin 开发,且能直接和 LeakCanary 做对比,理解"同样的问题,不同公司怎么解决"。
学习任务
- 读 README :
koom-java-leak/README.md,先搞清楚它解决的具体问题------为什么直接 dump hprof 会导致主进程卡死 - 理解核心机制:fork 子进程 + Copy-on-Write dump
- 搞清楚:为什么 fork 出的子进程可以在不影响主进程运行的情况下 dump 内存
- 搞清楚:COW 机制下,子进程"看到"的内存是什么时刻的快照
- 对比:如果不用 fork,直接在主进程 dump 会发生什么(GC 暂停、主线程阻塞)
- 对比 LeakCanary:LeakCanary 是怎么做的(弱引用 + 手动触发 dump),和 KOOM 的方案分别适合什么场景(debug 期 vs 线上)
- 读代码:定位到 fork dump 的具体实现代码,跟着调用链走一遍
本周产出(自测标准)
- 能用自己的话给别人讲清楚"为什么 fork+COW 能解决主进程卡死问题"
- 能画一张简单的流程图:从"检测到内存达到阈值"到"生成一份泄漏报告"整个链路
- 能说出 KOOM 这个方案相比 LeakCanary 的一个明确优势和一个明确限制
第 2 周:线程泄漏监控(koom-thread-leak)
为什么排第二:代码量最小,是学习 native hook 技术最好的入门素材。
学习任务
- 读 README :
koom-thread-leak/README.md,注意里面的 FAQ 部分(为什么只支持 Android N+、为什么不支持 armeabi-v7a) - 理解核心机制:hook
pthread_create/pthread_exit- 搞清楚什么是 hook(不修改原函数代码,拦截函数调用并插入自己的逻辑)
- 搞清楚 KOOM 依赖的 xhook 库大致是怎么做符号替换的(PLT hook 原理,不需要精通,理解思路即可)
- 理解"泄漏"判定逻辑 :一个 joinable 线程执行了
pthread_exit却没有被join/detach,为什么这算泄漏 - 深挖 FAQ 里的工程判断 :
- 为什么用 FP unwind(frame pointer unwind)而不是其他 unwind 方式
- 为什么这个技术选择导致 armeabi-v7a 不被支持(ARM/Thumb 混合指令导致 FP 不可靠)
本周产出
- 能解释什么是 hook,以及 KOOM 为什么要 hook 线程创建/退出函数而不是用其他方式监控线程
- 能理解"技术选型的 trade-off 如何限制了产品的适用范围"这个工程思维(这是本周最有价值的收获)
第 3 周:Native Heap 泄漏监控(koom-native-leak)
为什么放最后:技术难度最高,涉及 Tracing GC,建议先攻克更简单的两个模块建立信心和基础概念,再啃这块硬骨头。
学习任务
- 读 README :
koom-native-leak/README.md - 理解 Tracing GC(追踪式垃圾回收)思路 :
- 先搞清楚一般 GC 的可达性分析原理(从 GC Root 出发,标记可达对象,其余视为垃圾)
- 理解 KOOM 如何把这个思路"借用"到 native heap 分析上------native 内存本身没有 GC,但可以用同样的可达性分析找出"不可达但没释放"的内存块
- 理解如何 hook malloc/free 等分配函数,记录每一次分配的调用栈
- 理解输出内容:为什么报告里能直接给出"泄漏大小 + 分配调用栈",这对定位问题的价值在哪(对比:没有这个能力时,native 内存泄漏通常怎么排查,成本有多高)
本周产出
- 能说清楚"为什么可以用类似 GC 的思路去分析 native heap,这两者的核心相通点是什么"
- 能理解为什么"直接输出泄漏内存的分配调用栈"是这个模块最大的价值点
第 4 周:整合、实践与对比
目标:把前三周的碎片认知串成一个完整的系统理解,并落地到实践。
学习任务
- 通读
koom-monitor-base和koom-common:理解三个监控模块是怎么被一个统一的框架调度、初始化的 - 跑一遍
koom-demo:实际接入运行一次,观察真实产出的报告长什么样 - 手写一个简单场景:故意写一段 Java 对象泄漏 / 线程泄漏的代码,看 KOOM 能不能真的检测出来,报告是否准确
- 对比总结 :结合前面聊过的内容,写一份自己的对比笔记(KOOM vs LeakCanary vs Tencent/matrix),至少回答:
- 各自解决的核心场景差异是什么
- 如果让你给一个新项目做选型,你会怎么选,为什么
- (进阶,可选)读 Tencent/matrix 的 ResourceCanary 模块,用学到的 KOOM 知识去理解它的实现思路,验证自己是否真的"举一反三"了
本周产出(也是整个学习计划的验收标准)
- 能不看资料,独立向别人讲清楚 KOOM 三个模块各自的核心原理
- 能说出至少 3 个"设计决策的 trade-off"(比如 fork+COW vs 直接 dump、FP unwind 的取舍、hook 方式的选择)
- 能对着一份真实的 KOOM 报告,看懂里面的关键信息并判断问题大致出在哪
学习方式建议
- 不要死磕代码细节:C++ 部分如果某段实现看不懂,先理解"这段代码要干什么",跳过"每一行怎么写",除非你的目标是移植/魔改这个库
- 多问"为什么不这样做":每理解一个设计,都反问一遍"如果换个思路会怎样,作者为什么没这么选",这是积累工程判断力的关键
- 卡住随时来问我:遇到看不懂的代码片段、原理疑问,可以直接贴过来,我帮你拆解,比自己死磕效率高很多
- 做好笔记:建议每周写一份简短的笔记(哪怕只是几行要点),不需要精美,但要用自己的话总结,这比反复读代码更能巩固理解