2014-12-03 54 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