在开发过程中遇到一个比较奇怪的异常崩溃,错误堆栈信息如下:
java.lang.VerifyError: Verifier rejected class
com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1:
java.lang.Object com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1.invokeSuspend(java.lang.Object) failed to verify:
java.lang.Object com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1.invokeSuspend(java.lang.Object): [0xA5] 'this' argument 'Uninitialized Reference:
com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1$2 Allocation PC: 163' not instance of 'Precise Reference:
com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1$1' (declaration of 'com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1'
appears in /data/app/com.mg.phonecall-ijt_4dQsVJF3OzxQdk-w-Q==/base.apk!classes25.dex)
从网上找到了一些信息,有说是gradle版本低了的,也有说是Android Stuidio 的Instant Run导致的。但是经过分析,其实并不是。
在我这个项目中,使用的是Kotlin+协程的编码方式,而且是在加了协程的代码后才会出现此问题,所以我的第一感觉应该不是这两个原因导致的(Android Studio 4.2其实已经没有Instant Run了)。
然后经过详细的分析错误堆栈,发现问题其实是在:
'Uninitialized Reference: com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1$2 Allocation PC: 163' not instance of 'Precise Reference: com.xys.accessibility.process.VivoAccessbilityProcess$process$$inlined$apply$lambda$1$1'
可以发现,代码预期是
“***$process$$inlined$apply$lambda$1$2”
结果却是
“***$process$$inlined$apply$lambda$1$1”
这时候就想到,Kotlin大量的使用了*.apply{} *.let{} 的这种写法, 加上又使用了协程launch{},导致代码堆栈出现了大量的美元符号这种内部类的标记。
既然它出错的地方就在美元符号,那我们写代码时尽量减少这种代码不就可以了?所以按照这个思路进行了尝试,最终得到解决。
这个功能其实是很简单的,但是大量的使用了这种组合(Kotlin+协程)后, 导致编译器可能出现了编译错误或者运行时堆栈上的异常,最终导致崩溃。
解决方案:如果要使用协程,尽量减少.apply{} .let{} 这种代码,改成Java式的代码
注意:这个问题并不是总出现,估计还有一些原因没有考虑到。
网友评论