相关文章推荐
坏坏的蚂蚁  ·  软件项目管理案例教程第4版课后习题答案开发者社区·  1 周前    · 
跑龙套的蚂蚁  ·  Web 内容辅助功能准则- ...·  4 天前    · 
温文尔雅的火龙果  ·  学习类App岂容乱发荤段子_中华人民共和国最 ...·  4 天前    · 
个性的山寨机  ·  疫情防控期间免费开放虚拟仿真实验项目校外在线 ...·  昨天    · 
俊秀的勺子  ·  Apple Arcade ...·  16 小时前    · 
爱逃课的小狗  ·  中国大陆什么时候可以使用Copilot功能? ...·  2 月前    · 
眉毛粗的筷子  ·  “艰苦奋斗干惊天动地事,无私奉献做隐姓埋名人 ...·  11 月前    · 
体贴的仙人掌  ·  逼疯上海人的垃圾分类,德国人三十年前就在做了 ...·  1 年前    · 
纯真的足球  ·  WebLogic-XMLDecoder反序列 ...·  1 年前    · 
低调的警车  ·  ISO/IEC 29361:2008 - ...·  1 年前    · 
小百科  ›  妖怪般的VerifyError | 奇形怪状的bug开发者社区
fragment viewpager dialogfragment 软件
不拘小节的酸菜鱼
3 月前
逮虾户

妖怪般的VerifyError | 奇形怪状的bug

前往小程序,Get 更优 阅读体验!
立即前往
腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
圈层
工具
MCP广场
文章/答案/技术大牛
发布
首页
学习
活动
专区
圈层
工具
MCP广场
返回腾讯云官网
逮虾户
首页
学习
活动
专区
圈层
工具
MCP广场
返回腾讯云官网
社区首页 > 专栏 > 妖怪般的VerifyError | 奇形怪状的bug

妖怪般的VerifyError | 奇形怪状的bug

作者头像
逮虾户
发布 于 2022-03-06 09:46:01
发布 于 2022-03-06 09:46:01
1.1K 0 0
代码可运行
举报
文章被收录于专栏: 逮虾户 逮虾户
运行总次数: 0
代码可运行

theme: smartblue

前言

任何的 Transform 的字节都是危险的,所以如果真的觉得自己不能解决所有线上奇奇怪怪的问题,对这门技术还是要慎重。 出自很菜的虾。

如果你是因为这个bug,不幸点入这篇文章,我想说你运气属实不好,那么让我们掌声欢迎这个受害者。

首先我个人觉得这个问题非常难排查和定位,光从堆栈日志来说,你可能会一头雾水。

VerifyError问题排查

首先先看下这个异常的定义。

java.lang.VerifyError 是说 JVM 在加载一个类时,会去校验类的正确性,只有类文件不合法才会报这个Error,这个异常发生在类的加载过程中。

这个问题发生在类的生命周期的过程中。大体上还是和之前我写的那篇文章 一个一年没解决的ClassNotFoundException|类加载机制探索 这个问题非常类似。这个也是来b之前和字节大佬面试切磋时的一个问题吧,现在回头看看,其实还是受益匪浅,也大概知道这种问题如何去查看和调试了。

问题的本质还是之前说的androidx的升级。因为升级了fragment的版本到1.4.3,对于基础的fragment构造增加了一个有参的构造函数,之后导致了这个奇怪的问题。

在线上灰度的期间,我们发现了4.4的设备有这么个奇怪的 crash 异常。而在别的系统的设备则都是正常的。之后我们找了一台4.4的设备,发现在 release 版本的确会出现这个问题,异常情况如下所示。

代码语言: javascript
代码 运行次数: 0
运行
复制
FATAL EXCEPTION: main
at java.lang.VerifyError: androidx/fragment/app/DialogFragment
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2949)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:475)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1971)
at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311)
at androidx.fragment.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:249)
at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
at androidx.viewpager.widget.ViewPager.setCurrentItemInternal(ViewPager.java:669)
at androidx.viewpager.widget.ViewPager.setCurrentItemInternal(ViewPager.java:631)
at androidx.viewpager.widget.ViewPager.dataSetChanged(ViewPager.java:1086)
at androidx.viewpager.widget.ViewPager$PagerObserver.onChanged(ViewPager.java:3097)
at androidx.viewpager.widget.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:291)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5162)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(NativeStart.java)

现象很简单,这次我们所有的dialogfragment其实全挂了,在4.4的设备上,只要有这个的构造就会导致这个异常崩溃。

起初我们只是以为是混淆导致的这个异常情况的发生,但是尝试keep了所有androidx的类之后,发现这个问题还是稳定的复现,我有点懵逼了。

而之后简单的分析了下异常,猜测 dialogfragment 的类本身就出现了问题,所以导致了在类加载的时候,验证字节码安全性失败。但是这部分可是androidx内部的代码啊,这不就是不讲武德吗?

当自己走进死胡同的时候,还是可以尝试问下你周围的同事,也可以是你的大佬,正所谓一人计短。有时候的确是会有奇效的,也算是一个老司机理论了。

我大佬之前的确处理过类似的问题,但是他之前处理的那部分是所有机型都必挂,而且是和混淆相关。但是大佬的大佬也说了下,这种异常在崩溃日志之前就会有类信息校验的错误说明,也就是说 dalvikvm 在校验代码的时候会把错误的信息打印出来。恰巧就和之前的classnotfound异常对应上了。

代码语言: javascript
代码 运行次数: 0
运行
复制
06-15 18:11:16.876 13235-13235/? W/dalvikvm: VFY: invoke-direct <init> must be on current class or super
06-15 18:11:16.876 13235-13235/? W/dalvikvm: VFY:  rejecting opcode 0x70 at 0x0000
06-15 18:11:16.876 13235-13235/? W/dalvikvm: VFY:  rejected Landroidx/fragment/app/DialogFragment;.<init> (I)V

从描述上来看,就是构造函数内调用的是当前类的,并没有调用父类的构造。所以导致了这部分是一个异常的字节码。

因为这部分我司做了一部分字节码的父类替换,所以 DialogFragment 其实已经被修改了一部分了。而在新版本的 androidx 中,则给 Fragment 添加了另外一个有参的构造函数,所以这部分就出现了异常。

西内,无能狂怒,问题定位出来之后后续的其实也就相对来说还好了,改造方式则是有另外一个大佬去完成的,有兴趣可以参考下大佬之前写的lancet,功能也比较相似,细节我说出来可能要去趟hr办公室领离职证明了。

借住AS查看Apk的bytecode

另一个大佬顺便教会了我如何从apk中去查看最终产物的 bytecode 的方式。一个不需要用jadx反编译整个apk就可以快速查看 class 字节码的方式。

通过这部分就可以快速的查看这部分异常了,方式就和下面我所截图的一样了。

  1. 拖入android studio,点击apk
  1. 找到你想看的类,右键 show bytecode
  1. 看一看

这部分异常参考资料

Android 不想和你说话,抛了个 java.lang.VerifyError 这个是摘自另外一个哔哩哔哩的安卓巨佬了。

 
推荐文章
坏坏的蚂蚁  ·  软件项目管理案例教程第4版课后习题答案开发者社区
1 周前
跑龙套的蚂蚁  ·  Web 内容辅助功能准则- Microsoft Compliance | Microsoft Learn
4 天前
温文尔雅的火龙果  ·  学习类App岂容乱发荤段子_中华人民共和国最高人民检察院
4 天前
个性的山寨机  ·  疫情防控期间免费开放虚拟仿真实验项目校外在线资源(第一批 ...
昨天
俊秀的勺子  ·  Apple Arcade 將獲獎肯定的遊戲目錄擴增到超過180 款遊戲- Apple ...
16 小时前
爱逃课的小狗  ·  中国大陆什么时候可以使用Copilot功能? - Microsoft Q&A
2 月前
眉毛粗的筷子  ·  “艰苦奋斗干惊天动地事,无私奉献做隐姓埋名人” - 中国民族宗教网
11 月前
体贴的仙人掌  ·  逼疯上海人的垃圾分类,德国人三十年前就在做了-虎嗅网
1 年前
纯真的足球  ·  WebLogic-XMLDecoder反序列化分析 | Passer6y's Blog
1 年前
低调的警车  ·  ISO/IEC 29361:2008 - Information technology — Web Services Interoperability — WS-I Basic Profile Ver
1 年前
Link管理   ·   Sov5搜索   ·   小百科
小百科 - 百科知识指南