nuking nasty memory leaks
play

Nuking nasty memory leaks Pierre-Yves Ricau Pierre-Yves Ricau - PowerPoint PPT Presentation

LeakCanary Nuking nasty memory leaks Pierre-Yves Ricau Pierre-Yves Ricau dependencies { }A dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile


  1. 
 
 
 
 class NeoMobRealismView$1 extends LifecycleCallbacks { 
 private final NeoMobRealismView this$0; 
 public NeoMobRealismView$1(NeoMobRealismView this$0) { 
 this.this$0 = this$0; 
 } 
 @Override public void onActivityResumed(Activity activity) { 
 this$0.animate().alpha(1); 
 } 
 @Override public void onActivityPaused(Activity activity) { 
 this$0.animate().alpha(0); 
 } 
 } public class NeoMobRealismView extends View { 
 public NeoMobRealismView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 setBackgroundColor(getResources().getColor(R.color. ikb )); 


  2. In com.example.leakcanary:1.0:1. * com.example.leakcanary.MainActivity has leaked: * GC ROOT static android.app.ActivityThread.sCurrentActivityThread * references android.app.ActivityThread.mInitialApplication * references com.example.leakcanary.ExampleApplication.mActivityLifecycleCallbacks * references java.util.ArrayList.elementData * references array java.lang.Object[].[5] * references com.example.leakcanary.NeoMobRealismView$1.this$0 (anonymous subclass of com.example.leakcanary.ActivityLifecycleCallbacksAdapter) * references com.example.leakcanary.NeoMobRealismView.mContext * leaks com.example.leakcanary.MainActivity instance * Retaining: 673 B. * Reference Key: 8b2e09ef-1ea7-48da-b09e-7bf337f64473 * Device: LGE google Nexus 5X bullhead * Android Version: 7.0 API: 24 LeakCanary: 1.6-SNAPSHOT 050b554 * Durations: watch=1296983ms, gc=210ms, heap dump=33311ms, analysis=125485ms * Details: * Class android.app.ActivityThread | static DEBUG_BROADCAST = false | static TWO_COUNT_COLUMNS = java.lang.String@1873829608 (0x6fb05ee8) | static sCurrentActivityThread = android.app.ActivityThread@851460352 (0x32c04100) | static DEBUG_BACKUP = false

  3. * Details: * Class android.app.ActivityThread | static DEBUG_BROADCAST = false | static TWO_COUNT_COLUMNS = java.lang.String@1873829608 (0x6fb05ee8) | static sCurrentActivityThread = android.app.ActivityThread@851460352 (0x32c04100) | static DEBUG_BACKUP = false | static LOG_AM_ON_RESUME_CALLED = 30022 | static DEBUG_RESULTS = false | static LOG_AM_ON_STOP_CALLED = 30049 | static ONE_COUNT_COLUMN_HEADER = java.lang.String@1873816328 (0x6fb02b08) | static DEBUG_ORDER = false | static sPackageManager = android.content.pm.IPackageManager$Stub$Proxy@851448320 (0x32c01200) | static THUMBNAIL_FORMAT = android.graphics.Bitmap$Config@1879418296 (0x7005a5b8) | static SERVICE_DONE_EXECUTING_START = 1 | static REPORT_TO_ACTIVITY = true | static DEBUG_MEMORY_TRIM = false | static ACTIVITY_THREAD_CHECKIN_VERSION = 4 | static HEAP_COLUMN = java.lang.String@1873840320 (0x6fb088c0) | static $classOverhead = byte[1223]@1879556985 (0x7007c379) | static SERVICE_DONE_EXECUTING_STOP = 2 | static HEAP_FULL_COLUMN = java.lang.String@1873843888 (0x6fb096b0) | static SERVICE_DONE_EXECUTING_ANON = 0

  4. | [14] = null * Instance of com.example.leakcanary.NeoMobRealismView$1 | static $classOverhead = byte[664]@851688449 (0x32c3bc01) | this$0 = com.example.leakcanary.NeoMobRealismView@852252560 (0x32cc5790) | shadow$_klass_ = com.example.leakcanary.NeoMobRealismView$1 | shadow$_monitor_ = 0 * Instance of com.example.leakcanary.NeoMobRealismView | static $classOverhead = byte[6184]@851804161 (0x32c58001) | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = android.view.ViewPropertyAnimator@852248440 (0x32cc4778) | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@852305184 (0x32cd2520) | mBackgroundRenderNode = android.view.RenderNode@852339848 (0x32cdac88) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1098 | mCachingFailed = false | mClipBounds = null

  5. | [14] = null * Instance of com.example.leakcanary.NeoMobRealismView$1 | static $classOverhead = byte[664]@851688449 (0x32c3bc01) | this$0 = com.example.leakcanary.NeoMobRealismView@852252560 (0x32cc5790) | shadow$_klass_ = com.example.leakcanary.NeoMobRealismView$1 | shadow$_monitor_ = 0 * Instance of com.example.leakcanary.NeoMobRealismView | static $classOverhead = byte[6184]@851804161 (0x32c58001) | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = android.view.ViewPropertyAnimator@852248440 (0x32cc4778) | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@852305184 (0x32cd2520) | mBackgroundRenderNode = android.view.RenderNode@852339848 (0x32cdac88) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1098 | mCachingFailed = false | mClipBounds = null

  6. 
 
 public class View { 
 AttachInfo mAttachInfo; 
 public boolean isAttachedToWindow() { 
 return mAttachInfo != null; 
 } }

  7. StackTraceElement[] stackTrace = { 
 new StackTraceElement("com.foo.Foo", "bakeBaguette", "Foo.java", 42), 
 new StackTraceElement("com.foo.Bar", "bailarLaBamba", "Bar.java", 7), 
 }; 
 RuntimeException exception = new RuntimeException(); 
 exception.setStackTrace(stackTrace);

  8. 
 
 
 
 public final class BugsnagLeakUploader { 
 public BugsnagLeakUploader() {…} 
 public void uploadLeak(AnalysisResult result, String leakInfo) { 
 Throwable t = exception(result.className, result.leakTrace); 
 bugsnagClient.notify(t, Severity. WARNING , metadata); 
 } 
 private RuntimeException exception(String className, LeakTrace trace) {…} 
 }

  9. 
 
 public final class ViewRootImpl { static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C }D }E

  10. 
 
 public final class ViewRootImpl { static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C }D }E

  11. 
 
 public final class ViewRootImpl { static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C }D }E

  12. 
 
 public final class ViewRootImpl { static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C }D }EE

  13. 
 
 public final class ViewRootImpl { /** 
 * The run queue is used to enqueue pending work from Views when no Handler 
 * is attached. The work is executed during the next call to 
 * performTraversals on the thread. 
 */ static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C

  14. 
 
 public final class ViewRootImpl { /** 
 * The run queue is used to enqueue pending work from Views when no Handler 
 * is attached. The work is executed during the next call to 
 * performTraversals on the thread. 
 */ static final class RunQueue { 
 private final ArrayList<HandlerAction> mActions = new ArrayList<>(); 
 void post(Runnable action) { 
 postDelayed(action, 0); 
 }A 
 void postDelayed(Runnable action, long delayMillis) { 
 HandlerAction handlerAction = new HandlerAction(); 
 handlerAction.action = action; 
 handlerAction.delay = delayMillis; 
 synchronized (mActions) { 
 mActions.add(handlerAction); 
 }B 
 }C

  15. public class View { public void postOnAnimation(Runnable action) { 
 AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 attachInfo.mViewRootImpl.mChoreographer.postCallback( 
 Choreographer. CALLBACK_ANIMATION , action, null); 
 } else { 
 ViewRootImpl. getRunQueue ().post(action); 
 }A 
 }B public boolean post(Runnable action) { 
 final AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 return attachInfo.mHandler.post(action); 
 }E 
 ViewRootImpl. getRunQueue ().post(action); 
 return true; 
 }C }D

  16. public class View { public void postOnAnimation(Runnable action) { 
 AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 attachInfo.mViewRootImpl.mChoreographer.postCallback( 
 Choreographer. CALLBACK_ANIMATION , action, null); 
 } else { 
 ViewRootImpl. getRunQueue ().post(action); 
 }A 
 }B public boolean post(Runnable action) { 
 final AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 return attachInfo.mHandler.post(action); 
 }E 
 ViewRootImpl. getRunQueue ().post(action); 
 return true; 
 }C }D

  17. public class View { public void postOnAnimation(Runnable action) { 
 AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 attachInfo.mViewRootImpl.mChoreographer.postCallback( 
 Choreographer. CALLBACK_ANIMATION , action, null); 
 } else { 
 ViewRootImpl. getRunQueue ().post(action); 
 }A 
 }B public boolean post(Runnable action) { 
 final AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 return attachInfo.mHandler.post(action); 
 }E 
 ViewRootImpl. getRunQueue ().post(action); 
 return true; 
 }C }D

  18. public class View { public void postOnAnimation(Runnable action) { 
 AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 attachInfo.mViewRootImpl.mChoreographer.postCallback( 
 Choreographer. CALLBACK_ANIMATION , action, null); 
 } else { 
 ViewRootImpl. getRunQueue ().post(action); 
 }A 
 }B public boolean post(Runnable action) { 
 final AttachInfo attachInfo = mAttachInfo; 
 if (attachInfo != null) { 
 return attachInfo.mHandler.post(action); 
 }E 
 ViewRootImpl. getRunQueue ().post(action); 
 return true; 
 }C }D

  19. 
 public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>(); static RunQueue getRunQueue() { 
 RunQueue queue = sRunQueues .get(); 
 if (queue != null) { 
 return queue; 
 }A 
 queue = new RunQueue(); 
 sRunQueues .set(queue); 
 return queue; 
 }B }C

  20. 
 public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>(); static RunQueue getRunQueue() { 
 RunQueue queue = sRunQueues .get(); 
 if (queue != null) { 
 return queue; 
 }A 
 queue = new RunQueue(); 
 sRunQueues .set(queue); 
 return queue; 
 }B }C

  21. 
 public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>(); static RunQueue getRunQueue() { 
 RunQueue queue = sRunQueues .get(); 
 if (queue != null) { 
 return queue; 
 }A 
 queue = new RunQueue(); 
 sRunQueues .set(queue); 
 return queue; 
 }B }C

  22. 
 public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>(); static RunQueue getRunQueue() { 
 RunQueue queue = sRunQueues .get(); 
 if (queue != null) { 
 return queue; 
 }A 
 queue = new RunQueue(); 
 sRunQueues .set(queue); 
 return queue; 
 }B }C

Recommend


More recommend