分析由RenderNode溢出,引出应用闪退,

今天拿到一个钉钉闪退的问题,
main log如下:
05-18 18:25:05.969737 360 360 W Layer : [com.alibaba.android.rimet/com.alibaba.android.rimet.biz.home.activity.HomeActivity] opaque layer with plane alpha:0.56 cannot be handled by hwcomposer
05-18 18:25:05.970757 1885 1885 D LiuHaiSignalClusterView: apply(2), mMobileVisible= true, mIsAirplaneMode= false, mNoSimsVisible= false
05-18 18:25:05.970958 1885 1885 D LiuHaiSignalClusterView: showViewInWfcCase: mSubId = 2, mIsWfcCase=false
05-18 18:25:05.972224 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] JNI ERROR (app bug): weak global reference table overflow (max=51200)
05-18 18:25:05.972285 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] weak global reference table dump:
05-18 18:25:05.972296 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] Last 10 entries (of 51200):
05-18 18:25:05.972304 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51199: 0x15645370 android.view.RenderNode
05-18 18:25:05.972315 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51198: 0x156008f8 android.view.RenderNode
05-18 18:25:05.972323 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51197: 0x155e5850 android.view.RenderNode
05-18 18:25:05.972330 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51196: 0x155e5a60 android.view.RenderNode
05-18 18:25:05.972338 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51195: 0x155d1658 android.view.RenderNode
05-18 18:25:05.972346 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51194: 0x15559568 android.view.RenderNode
05-18 18:25:05.972354 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51193: 0x15559808 android.view.RenderNode
05-18 18:25:05.972361 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51192: 0x15559ac0 android.view.RenderNode
05-18 18:25:05.972370 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51191: 0x1554f328 android.view.RenderNode
05-18 18:25:05.972378 25153 25153 F art : art/runtime/indirect_reference_table.cc:132] 51190: 0x1554f850 android.view.RenderNode

我一看,慒B了,居然有全局变量超过5万多个对象,什么概念,

再细看一下溢出的对象类型,RendorNode, 查看了一下代码,这个类是与硬件加速相关的

好吧,先来看一下这个类的对象在哪创建的,

    public View(Context context) {
        mContext = context;
        mResources = context != null ? context.getResources() : null;
        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
        // Set some flags defaults
        mPrivateFlags2 =
                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        mRenderNode = RenderNode.create(mName + hashCode, this);

    View() {
        mResources = null;
        /// M: name for rendernode @{
        mName = getClass().getName();
        String hashCode = "";
        try {
            hashCode = " @" + Integer.toHexString(this.hashCode());
        } catch (Exception e) {
            /// M: Do nothing
        }
        mRenderNode = RenderNode.create(mName + hashCode, this);
        /// @}
    }

可以看到,只要是view初始化了,即有一个RenderNode对象,当然 View里面还有一个mBackgroundRenderNode对象,也差不多,这里我就不细说了,

那它在什么时候释放呢,怎样释放

RenderNode实际是一个带有Native指针的对象,只有释放掉这个指针,才算把这个对象释放掉

我查了一下代码,只有nSetDisplayList这个RenderNode的Native函数有此功能

public void discardDisplayList() {
    if (!mValid) return;

    nSetDisplayList(mNativeRenderNode, 0);
    mValid = false;
}

所以,只有调用了这个函数,才会释放掉RenderNode对象

那它在什么时候会被调用呢,

实际上,是在onRenderNodeDetached, View类的resetDisplayList中会被调用,

但这里有区别吗?

有的, 区别在于, onRenderNodeDetached调用在于这个RenderNode之前被渲染过了,但View中的resetDisplayList并不是这样的,它可能是被渲染过,可能是因为窗口突然消失

那么结果出来了, 针对第一种onRenderNodeDetached,我们就必须判断RenderNode的有效性,但对第二种来说,RenderNode就应该无条件被回收,

从上面的代码来看,是针对第一种的写法, 但第二种也被覆盖了,所以会出问题

修改方法非常简单 ,即在RenderNode中实现一个不需要判断有效性的回收方法即可,而且在View中回调

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值