解读《Android Camera内存问题剖析 》

解读《Android Camera内存问题剖析》,简单概括一下。

  一看作者大名有点熟悉,原来曾是同事,不知道什么时候跳走的。以前调研 android app 内存泄漏监测方案时,曾在内网跟他请教问题,很热心,直接给了源码参考。遇到的大牛大都如此,乐于助人、慷慨、开源、分享。至于那些藏着掖着(可能是真不会)、更有甚者整天只会说这不行那不行(PUA套路),就是不说怎么能行的,有多远 get out 多远。

问题:

  抖音app(android 版)线上发现大量 camera 相关内存泄漏造成的 OOM 的 crash。

原因:

  native 对象(CameraMetadata)依赖上层 Java 的 finalize 方法(GC)来释放 native 内存:Java GC 时,CameraMetadataNative.java 的 finalize 方法——调用 close 方法——调用 nativeClose 方法——调用 C++ native 的 CameraMetadata_close 方法来 delete CameraMetadata 对象。

  问题发生在 Java 层的对象所占内存较小,很难在一定时间内触发 GC,但该 Java 层对象连续在 native 层创建小对象,导致其间接引用的 native 内存不断上涨,最终触发虚拟内存上限而 crash。

解决方案:

  应用层使用完 CameraMetadataNative 对象后,反射调用其 close 方法(private方法)来主动释放其所引用的 native 内存。(当然主动GC也能解决但太影响体验)

经验教训:

  应用在尽可能减少泄漏的同时,也应该努力降低自身 native 内存水位。AOSP 里利用 Java 的 finalize 方法来释放其间接引用的 native 内存是个偷懒挖坑的设计,类似的案例在 AOSP 里比比皆是。我们在实际开发中,类似内存这种有限的资源应及时回收,甚至可以主动限定对象的生命周期,一旦完成使命就主动回收其占用的内存,避免使用 finalize 逻辑来释放 native 内存。