【问题标题】:Binder preventing garbage collectionBinder 防止垃圾收集
【发布时间】:2011-12-20 01:14:10
【问题描述】:

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

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

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

我相信它会导致有趣的情况,如果 Activity 中的回调指向内存密集型的东西,则在收集服务中的回调之前不会收集它。如果 Service 的内存不低,它可能很长一段时间都不会收集回调,回调可能只是在 Activity 中建立,直到 Activity 中出现 OutOfMemoryError。

【问题讨论】:

    标签: android ipc android-binder


    【解决方案1】:

    如果我正确理解 Binder 的工作原理,您的问题如下。对于每个传入的来电,您的服务创建一个单独的线程。当您将对象传递给该线程时,您的 Binder 系统会为该线程创建对象的本地副本。因此,在您的 Service 方法返回结果之前,带有对象副本的线程将继续工作。

    要检查这一点,只需尝试查看您的服务进程的线程(在 DDMS 中)。

    【讨论】:

      【解决方案2】:

      Yury 是非常正确的。

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

      但是Activity中的回调对象会一直被Android的binder系统指向,直到Service中对应的回调对象被垃圾回收。

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

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

      这带来了一个有趣的想法,如果非静态内部回调类的父类是 Activity,并且在通过 binder 发送回调之后但在调用之前发生配置更改(例如屏幕旋转)那时回调将在执行时指向一个旧的 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());
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-18
        • 1970-01-01
        • 1970-01-01
        • 2012-05-15
        • 2013-03-19
        • 2017-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多