Open cyrushine opened 1 year ago
https://juejin.cn/post/7136063993537363975
https://ljd1996.github.io/2022/08/24/Android-%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%BA%BF%E4%B8%8AOOM%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86/
Java 里的析构函数 finalize(),override 此函数且不是空函数的叫做 f 类
finalize()
当 f 类的实例被创建时,会调用 FinalizerReference.add 将此 f 实例包装为 FinalizerReference
FinalizerReference.add
FinalizerReference
然后在 gc 时被线程 ReferenceQueueDaemon 放入引用队列 FinalizerReference.queue
ReferenceQueueDaemon
FinalizerReference.queue
线程 FinalizerDaemon 阻塞在 FinalizerReference.queue 队列上,当队列里有元素出队时,调用其 finalize() 方法
FinalizerDaemon
线程 FinalizerWatchdogDaemon 监控 FinalizerDaemon 和 ReferenceQueueDaemon 这两个线程的一次执行时长,如果超时则抛出 TimeOutException,这个超时阈值在 AOSP 里定义为 10s
FinalizerWatchdogDaemon
TimeOutException
native 层由于业务逻辑代码有 bug 导致存在内存泄漏的风险,这个 bug 可能存在很久了,只是以前没有把析构方法放在 finalize() 里,即使在 native 层发生了内存泄漏也不会导致 OOM,并且由于缺乏 native 层的内存监控机制一直没有发现,此次改造是由于连累了 java 对象不能被 gc 释放导致 OOM 才发现的
https://juejin.cn/post/7136063993537363975
https://ljd1996.github.io/2022/08/24/Android-%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%BA%BF%E4%B8%8AOOM%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86/
Java 里的析构函数
finalize()
,override 此函数且不是空函数的叫做 f 类当 f 类的实例被创建时,会调用
FinalizerReference.add
将此 f 实例包装为FinalizerReference
然后在 gc 时被线程
ReferenceQueueDaemon
放入引用队列FinalizerReference.queue
线程
FinalizerDaemon
阻塞在FinalizerReference.queue
队列上,当队列里有元素出队时,调用其finalize()
方法线程
FinalizerWatchdogDaemon
监控FinalizerDaemon
和ReferenceQueueDaemon
这两个线程的一次执行时长,如果超时则抛出TimeOutException
,这个超时阈值在 AOSP 里定义为 10snative 层由于业务逻辑代码有 bug 导致存在内存泄漏的风险,这个 bug 可能存在很久了,只是以前没有把析构方法放在
finalize()
里,即使在 native 层发生了内存泄漏也不会导致 OOM,并且由于缺乏 native 层的内存监控机制一直没有发现,此次改造是由于连累了 java 对象不能被 gc 释放导致 OOM 才发现的