gpt4 book ai didi

android - Binder 防止垃圾回收

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:28:21 25 4
gpt4 key购买 nike

我想我追踪到了内存泄漏,并想确认我认为 Android 的 Binder 是如何实现的。在这种情况下,我有一个服务和一个 Activity ,每个都在自己的进程中。我创建了一个 AIDL,它允许我通过 ipc 方法将回调对象从 Activity 传递到服务,然后在服务完成请求的任务时调​​用回调。

很长一段时间我都在想:如果我将一个新的回调对象传递给服务并且我没有在我的 Activity 中保留指向回调对象的指针为什么垃圾收集器不继续进行并在我的 Activity 进程中收集回调?既然这似乎没有发生,JVM 如何知道何时在我的 Activity 中垃圾收集回调。

我想答案是Binder系统在Activity进程中保留了一个指向我的Callback的指针,直到Service进程中对应的Callback对象调用了它的finalize()方法,然后发送消息给Activity释放指针。 这是正确的吗?如果不是,它是如何工作的?

我相信它会导致有趣的情况,如果 Activity 中的回调指向非常占用内存的东西,则在收集服务中的回调之前不会收集它。如果 Service 的内存不低,它可能很长时间都不会收集回调,并且回调可能会在 Activity 中累积,直到 Activity 中出现 OutOfMemoryError。

最佳答案

Yury 非常正确。

我的服务启动了一个线程来保存回调,当线程完成其工作时它调用回调并且线程结束。当回调被调用时,它可能会在我的 Activity 中做一点点工作然后返回,此时我的 Activity 进程中没有指向回调的指针。

但是,Activity 中的回调对象将继续被 Android 的绑定(bind)器系统指向,直到 Service 中相应的回调对象被垃圾回收。

如果 Activity 进程中的回调对象控制了一些消耗大量内存的其他对象,那么我就会无缘无故地浪费我的 Activity 进程中的内存,甚至可能会出现 OutOfMemoryError。 解决方案是在我的回调类中创建一个名为 destory() 的简单方法来清空所有回调的字段并在我完成回调时调用该方法。

如果回调类是一个非静态内部类,您可能需要考虑将其更改为静态内部类,并在构造函数中传入父类,这样您也可以在 中取消它destory() 方法。

这引发了一个有趣的想法,如果非静态内部回调类的父类是一个 Activity,并且在回调通过绑定(bind)器发送之后但在调用之前发生了配置更改(例如屏幕旋转)那时回调将在执行时指向一个旧的 Activity 对象!

更新:我在 Binder.java 中发现了这段代码,当然它被禁用了,但如果他们在 Javadocs 中提到这种东西就更好了。

    if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Binder> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}

关于android - Binder 防止垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7976322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com