主要观点总结
某应用经历灰度发布后出现线上ANR告警,排查后定位到页面onCreate方法执行过久,经火焰图及反编译发现本应是if语句的代码变成了do-while语句,导致主线程卡死。问题涉及自定义插桩工具weaver和R8编译工具。通过分析字节码和ASM方法复制原理,最终定位到多线程并发复制methodNode时导致的labelNode对象被替换的问题。通过增加类锁解决了问题。
关键观点总结
关键观点1: 背景介绍
应用经历灰度发布后线上出现ANR告警,定位到页面onCreate方法执行过久,经查火焰图和反编译发现代码逻辑异常。
关键观点2: 问题分析
初步分析是if和do-while语句互相转化的问题,涉及R8编译工具和自定义插桩工具weaver。通过对字节码和插桩原理的分析,定位到多线程并发复制methodNode导致的labelNode对象被替换的问题。
关键观点3: 解决方法
通过增加类锁解决多线程并发复制methodNode的问题,确保每个线程的复制操作互不干扰。
关键观点4: 总结
问题是由于字节码异常在多线程环境下引发的,对于涉及代码编辑操作的插件开发,需要特别关注并发场景下的稳定性。此类问题在业务规模扩大或环境变更时可能更容易出现。
文章预览
目录 一、背景 二、问题分析 1. 初步分析 2. 分析R8 3. 分析weaver 4. 揭露谜底 三、修复方案 四、总结 一 背景 某次灰度发布之后没多久就收到线上ANR告警,经排查定位到是某个页面onCreate方法执行太久导致,而火焰图中的耗时堆栈指向了我们用于监控页面启动速度的一段插桩代码,反编译Apk之后发现本该是if语句的代码竟变成了一个do-while语句,形成了死循环最终导致主线程卡死。 此后每构建二、三十次都会复现一次该问题,且每次的异常页面,异常方法完全随机。 二 问题分析 if和do-while两个完全不相干的语句为什么出现互相转化的情况?在jadx反编译而来的smali代码中不难看出,if语句对应的标签正常情况下应该指向的是return语句,和Java源码中if语句块后面紧跟着return语句对应。而异常情况下标签跑到了整个函数的开头,故被jadx
………………………………