LeakCanary

来源:互联网 发布:windows系统备份 编辑:程序博客网 时间:2024/05/01 14:10

在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.exceptIv10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * references android.widget.ImageView.mContext10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * leaks com.picasso.beautyread.DrawerLayoutActivity instance10-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-bd0462cd33d110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Device: HUAWEI Honor Che1-CL10 Che1-CL1010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Android Version: 4.4.4 API: 19 LeakCanary: 1.3.110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ * Durations: watch=5021ms, gc=150ms, heap dump=711ms, analysis=22257ms10-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.PullRefreshRecyclerView10-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.ImageView10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUri = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mColorFilter = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawable = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableHeight = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableWidth = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mHaveFrame = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLevel = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mCropToPadding = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMaxHeight = 214748364710-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMaxWidth = 214748364710-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMergeState = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mResource = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mColorMod = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mBaselineAlignBottom = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mBaseline = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAlpha = 25510-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAdjustViewBoundsCompat = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mViewAlphaScale = 25610-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAdjustViewBounds = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUnsetPressedState = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAccessibilityDelegate = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mUnscaledDrawingCache = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAnimator = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mAttachInfo = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTouchDelegate = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mTag = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mSendViewStateChangedAccessibilityEvent = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mClipBounds = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mContentDescription = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDisplayList = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawableState = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mDrawingCache = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mSendViewScrolledAccessibilityEvent = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mFloatingTreeObserver = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mScrollCache = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mHardwareLayer = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mInputEventConsistencyVerifier = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mKeyedTags = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPendingCheckForTap = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPendingCheckForLongPress = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLayerPaint = null10-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 = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasureCache = null10-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 = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMatchIdPredicate = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMatchLabelForPredicate = null10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLeftPaddingDefined = false10-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasuredHeight = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMeasuredWidth = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMinHeight = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mMinWidth = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusDownId = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusForwardId = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusLeftId = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusRightId = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mNextFocusUpId = -110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOldHeightMeasureSpec = -214748364810-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOldWidthMeasureSpec = -214748364810-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mOverScrollMode = 110-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mLeft = 010-20 16:09:24.860  22628-25692/com.picasso.beautyread D/LeakCanary﹕ |   mPaddingBottom = 010-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

0 0