LeakCanary

在Android开发中,OOM(内存泄露)已经是老生常谈的事情了,之前也有许多工具来检测内存泄露,比如比较常用的MAT,但是MAT使用步骤太麻烦了,近来发现了一个新工具,LeakCanary,它是一个用来检查 Android 下内存泄漏的开源库。

用法
首先集成 LeakCanary 库

dependencies {
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}

在 debug 版本上,集成 LeakCanary 库,并执行内存泄漏监测,而在 release 版本上,集成一个无操作的 wrapper ,这样对程序性能就不会有影响。

在Application 中

/**
 * User: Picasso(380643397@qq.com)
 * Date: 2015-10-20
 * Time: 15:26
 * FIXME
 */
public class BRApplication extends Application {
    private RefWatcher mRefWatcher;

    public static RefWatcher getRefWatcher(Context context) {
        BRApplication application = (BRApplication) context.getApplicationContext();
        return application.refWatcher;
    }

    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        refWatcher = LeakCanary.install(this);
    }

}

LeakCanary.install() 返回一个配置好了的 RefWatcher 实例。它同时安装了 ActivityRefWatcher 来监控 Activity 泄漏。即当 Activity.onDestroy() 被调用之后,如果这个 Activity 没有被销毁,logcat 就会打印出如下信息告诉你内存泄漏发生了。

eg. 我在一个项目中加入此工具,运行发现出现如下log

10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ In com.picasso.beautyread:1.6:7.
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * com.picasso.beautyread.DrawerLayoutActivity has leaked:
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * GC ROOT static com.picasso.beautyread.custom.PullRefreshRecyclerView.exceptIv
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * references android.widget.ImageView.mContext
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * leaks com.picasso.beautyread.DrawerLayoutActivity instance
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ [ 10-20 16:09:24.860 22628:25692 D/LeakCanary ]
    * Reference Key: 7e7ce215-94ea-422b-bd5f-bd0462cd33d1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Device: HUAWEI Honor Che1-CL10 Che1-CL10
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Android Version: 4.4.4 API: 19 LeakCanary: 1.3.1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Durations: watch=5021ms, gc=150ms, heap dump=711ms, analysis=22257ms
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ [ 10-20 16:09:24.860 22628:25692 D/LeakCanary ]
    * Details:
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Class com.picasso.beautyread.custom.PullRefreshRecyclerView
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static $staticOverhead = byte[] [id=0x42413d31;length=48;size=64]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static exceptIv = android.widget.ImageView [id=0x424efdf8]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static exceptTv = android.support.v7.widget.AppCompatTextView [id=0x424f09e0]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Instance of android.widget.ImageView
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static $staticOverhead = byte[] [id=0x4194d949;length=48;size=64]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static sS2FArray = android.graphics.Matrix$ScaleToFit[] [id=0x4183fa40;length=4]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   static sScaleTypeArray = android.widget.ImageView$ScaleType[] [id=0x4182cfa8;length=8]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mXfermode = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUri = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTempSrc = android.graphics.RectF [id=0x424f07a0]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTempDst = android.graphics.RectF [id=0x424f07c0]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mState = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mColorFilter = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mScaleType = android.widget.ImageView$ScaleType [id=0x418369b8]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMatrix = android.graphics.Matrix [id=0x424f07e0]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawMatrix = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawable = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableHeight = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableWidth = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mHaveFrame = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLevel = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mCropToPadding = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMaxHeight = 2147483647
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMaxWidth = 2147483647
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMergeState = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mResource = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mColorMod = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mBaselineAlignBottom = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mBaseline = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAlpha = 255
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAdjustViewBoundsCompat = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mViewAlphaScale = 256
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAdjustViewBounds = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUnsetPressedState = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAccessibilityDelegate = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUnscaledDrawingCache = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAnimator = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAttachInfo = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mBackground = android.graphics.drawable.BitmapDrawable [id=0x424f0710]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTransformationInfo = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTouchDelegate = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTag = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mSendViewStateChangedAccessibilityEvent = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mClipBounds = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mContentDescription = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mContext = com.picasso.beautyread.DrawerLayoutActivity [id=0x42183e18]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mCurrentAnimation = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDisplayList = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableState = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawingCache = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mSendViewScrolledAccessibilityEvent = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mFloatingTreeObserver = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mScrollCache = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mHardwareLayer = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mResources = com.huawei.android.content.res.ResourcesEx [id=0x41a4c658]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPerformClick = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mInputEventConsistencyVerifier = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mKeyedTags = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPendingCheckForTap = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPendingCheckForLongPress = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLayerPaint = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mParent = android.widget.RelativeLayout [id=0x424ef950]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLayoutInsets = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLayoutParams = android.widget.RelativeLayout$LayoutParams [id=0x424f0818]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOverlay = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasureCache = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mListenerInfo = android.view.View$ListenerInfo [id=0x424f0958]
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLocalDirtyRect = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMatchIdPredicate = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMatchLabelForPredicate = null
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLeftPaddingDefined = false
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasuredHeight = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasuredWidth = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMinHeight = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMinWidth = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusDownId = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusForwardId = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusLeftId = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusRightId = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusUpId = -1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOldHeightMeasureSpec = -2147483648
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOldWidthMeasureSpec = -2147483648
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOverScrollMode = 1
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLeft = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPaddingBottom = 0
10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPaddingLeft = 0

从log中很容易看出来,问题出在文件PullRefreshRecyclerView的对象exceptIv,一看源代码发现:

 /**
     * 异常图片控件
     */
    private static ImageView exceptIv;

定义的时候多写了个static,但是这里根本不需要使用static,把static去掉运行,OK~~

使用非常方便!

参考博客
http://www.jianshu.com/p/0049e9b344b0
https://github.com/square/leakcanary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值