2014-12-03 109 views
4

我使用MemoryAnalyzer工具来查找我的Android应用程序中的内存泄漏。因此,我运行我的应用程序,访问所有活动,然后按回直到进入桌面。然后,我使用DDMS获取内存转储(已按下原因GC几次)。内存泄漏,由于android.widget.BubblePopupHelper

然后我使用OQL查询select * from instanceof android.app.Activity找到漏水的活动,然后按合并最短路径的GC根 - >排除泄漏对象的所有幻象/弱/柔和/等引用。在这里,我看到这样的画面:

enter image description here

如此看来,在系统某处有一个静态对象BubblePopupHelper.sHelper,它保留从我的活动的EditText视图的引用,使整个活动泄漏!但这是什么BubblePopupHelperofficial docs我找不到关于此课程的任何信息。我怎样才能防止我的活动被这个奇怪的对象引用而留在内存中?

我测试LG L40设备上,运行API19

+0

我今天发现了这个,也是在一个带有API19的LG设备上。 @Blackbelt这绝对是一个泄漏,因为这个活动被破坏了,应该已经被垃圾收集了,但是由于这个静态字段,它在堆中仍然活着。在我的情况下,我在创建堆转储之前打开了一个简单而小的活动,以便我可以轻松识别任何其他活动的泄漏。 – dsh 2016-03-03 19:13:43

回答

8

我检漏工具报告相同的泄漏定期,仅LG手机:

object com.squareup.SomeActivity 
`-mContext of object android.widget.EditText 
    `-mView of object android.widget.BubblePopupHelper 
    `-sHelper of class android.widget.BubblePopupHelper 

制造商想改变私有的API引擎盖下的Android SDK。这是由LG引入的内存泄漏。

从我可以收集的内容来看,聚焦的EditText使用BubblePopupHelper,可能会显示一些复制/粘贴弹出窗口或文本句柄。由于一次只有一个重点编辑文本,因此他们将帮助器设置为单例,并保持对最新编辑文本的引用。

因此,这意味着整个活动&其整个视图层次结构将泄漏,直到另一个编辑文本得到关注。

你怎么解决这个问题?不幸的是,这是SDK代码,所以虽然这可能在未来的LG版本中得到修复,但总会有一些用户出现这种错误。

虽然这个错误当然不是你的错,但它仍然是一个内存泄漏,它可能会泄漏增加OutOfMemory错误。所以,这是值得尝试修复它,

有一种方法,但它不漂亮。当活动被破坏时,您可以使用反射来清除泄漏。例如,一种方法可以是清除sHelper字段,或者另一种方法是清除帮助器上的mView字段。无论哪种方式,你应该尝试在设备上(我现在没有),看看它是否有效。

private static final Executor backgroundExecutor = 
    newCachedThreadPool(backgroundThreadFactory("android-leaks")); 

public static void fixLGBubblePopupHelper(final Application application) { 
    backgroundExecutor.execute(new Runnable() { 
    @Override public void run() { 
     final Field sHelperField; 
     try { 
     Class<?> bubbleClass = Class.forName("android.widget.BubblePopupHelper"); 
     sHelperField = bubbleClass.getDeclaredField("sHelper"); 
     sHelperField.setAccessible(true); 
     } catch (Exception ignored) { 
     // We have no guarantee that this class/field exists. 
     return; 
     } 
     application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksAdapter() { 
     @Override public void onActivityDestroyed(Activity activity) { 
      try { 
      sHelperField.set(null, null); 
      } catch (IllegalAccessException ignored) { 
      } 
     } 
     }); 
    } 
    }); 
} 
+0

试图寻找LGs网站上的联系人的错误报告,但其黑洞的可怕。 – trippedout 2015-08-03 20:16:25