Android 内存泄露分析之MAT工具分析

MAT JDK下载地址

链接:https://pan.baidu.com/s/13ESnQDksLYA15GQh8_JldQ 
提取码:jhhp 

工具mat. eclipse memory analyzer

1.转换为标准hprof
hprof-conv -z in. hprof  out.hprof  //hprof-conv sdk下面的工具

2. mat打开out.hprof

3.查看Leak Suspects,大概是泄露在哪里,不过一般没什么价值

4.点击histogram图标(左边第二个图标)
5.查看那种最多,比如app一般搜索PhoneWindow,可以看到有多少泄露。假如很多的话就证明就是这里发生内存泄露,

6.选择右键list objects-- with incoming reference,会看到这些窗口是来至于哪里

7.选择右键path to gc roots -- exclude all platform/ weak/ soft etc references 看到gc过程可以看到是什么对象没有回收导致泄露

8.使用OQL ( open object query language)
查询对象泄露的个数,比如
select * from com. android. settings. Settings$NetworkDashboardActivity,上面有个感叹号图标执行搜索F5

 

实例

AccessibilityStateChangeListener内存泄露例子,在hprof文件中发现了300个此对象,这是不应该的。此对象是在ViewRootImpl初始化时add,在doDie时remove,这里泄露的话,原因就是为啥doDie没执行或者没执行最后的remove。查看log是因为没有成对的执行dispatchDetachedFromWindow,原因是mAdded为false

//AccessibilityStateChangeListener内存泄露例子

public ViewRootImpl(Context context, Display display) {
    mAccessibilityManager.addAccessibilityStateChangeListener(
            mAccessibilityInteractionConnectionManager, mHandler);
    mHighContrastTextManager = new HighContrastTextManager();
    mAccessibilityManager.addHighTextContrastStateChangeListener(
            mHighContrastTextManager, mHandler);
            
    mAdded = false;
}

@/frameworks/base/core/java/android/view/accessibility/AccessibilityManager.java
public void addAccessibilityStateChangeListener(
        @NonNull AccessibilityStateChangeListener listener, @Nullable Handler handler) {
    synchronized (mLock) {
        mAccessibilityStateChangeListeners
                .put(listener, (handler == null) ? mHandler : handler);
    }
}

//removeAccessibilityStateChangeListener
void dispatchDetachedFromWindow() {
    mAccessibilityManager.removeAccessibilityStateChangeListener(
            mAccessibilityInteractionConnectionManager);
    mAccessibilityManager.removeHighTextContrastStateChangeListener(
            mHighContrastTextManager);
    removeSendWindowContentChangedCallback();
}


void doDie() {
    checkThread();
    if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
    synchronized (this) {
        if (mRemoved) {
            return;
        }
        mRemoved = true;
        if (mAdded) {
            dispatchDetachedFromWindow();
        }

        mAdded = false;
    }
    WindowManagerGlobal.getInstance().doRemoveView(this);
}

mAdded是因为发生了异常导致mAdded未false,就不能remove对象,就造成泄露


public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
            mAdded = true;
            try {
                mOrigWindowType = mWindowAttributes.type;
                mAttachInfo.mRecomputeGlobalAttributes = true;
                collectViewAttributes();
                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(),
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mInputChannel);
            } catch (RemoteException e) {
                mAdded = false;
                throw new RuntimeException("Adding window failed", e);
            } finally {
                if (restore) {
                    attrs.restore();
                }
            }

            mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
            if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
            if (res < WindowManagerGlobal.ADD_OKAY) {
                mAdded = false;

                switch (res) {
                    case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
                    case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
                        throw new WindowManager.BadTokenException(
                                "Unable to add window -- token " + attrs.token
                                + " is not valid; is your activity running?");
                }
                throw new RuntimeException(
                        "Unable to add window -- unknown error code " + res);
            }

        }
    }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值