今天拿到一个钉钉闪退的问题,
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中回调