2014-12-03 2 views
4

MemoryAnalyzer 도구를 사용하여 Android 애플리케이션에서 메모리 누수를 찾습니다. 따라서 응용 프로그램을 실행하고 모든 활동을 방문한 다음 바탕 화면에이를 때까지 뒤로 누르십시오. 그런 다음 DDMS를 사용하여 메모리 덤프를 가져옵니다 (원인 : GC 여러 번 클릭). > 유출 된 개체에 대한 모든 팬텀/약/소프트/등 참조 제외 -android.widget.BubblePopupHelper로 인한 메모리 누수

은 뿌리를 GC하는 최단 경로를 병합 그럼 누출 활동을 찾기 위해 OQL 쿼리 select * from instanceof android.app.Activity을 사용하고 를 누릅니다.

enter image description here

그래서 어딘가에 시스템의 전체 활동이 누출 원인, 내 활동에서 EditText보기에 대한 참조를 유지하는 정적 객체 BubblePopupHelper.sHelper,이 보인다 : 그리고 여기 내가이 사진을 가지고! 그러나 이것은 무엇입니까 BubblePopupHelper? official docs에서이 수업에 대한 정보를 찾을 수 없습니다. 그리고이 이상한 물건에 의해 참조되기 때문에 나의 활동이 기억 속에 유지되는 것을 어떻게 막을 수 있습니까?

내가

+0

오늘 나는 또한 API19가있는 LG 기기에서이 사실을 발견했습니다. @Blackbelt 이것은 활동이 파괴되어 가비지 수집을해야했기 때문에 확실히 누수입니다. 그러나이 정적 필드로 인해 힙에 활성 상태로 유지됩니다. 제 경우에는 힙 덤프를 만들기 전에 간단하고 작은 활동을 열었으므로 다른 활동의 누출을 쉽게 식별 할 수있었습니다. – dsh

답변

8

내 누출 탐지 도구는 LG 폰에서 정기적으로 같은 누출 신고 API19을 실행, LG L40 장치에서 테스트되었습니다 제조사 전용 API를 변경하려면

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

후드 안드로이드 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

은 버그 신고를 위해 LG 사이트에서 연락처를 찾으려고 시도했지만 그 끔찍한 블랙홀을 발견했습니다. – trippedout