记一次overloadaggressively造成的崩溃

将Kotlin版本从1.1.2-4升级到1.3.11后,发现打的release包开机就会崩溃:崩溃日志为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
java.lang.RuntimeException: Unable to instantiate application com.tencent.sigma.patch.HotPatchApplication: java.lang.ClassNotFoundException: Didn't find class "com.tencent.sigma.patch.HotPatchApplication" on path: DexPathList[[zip file "/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk"],nativeLibraryDirectories=[/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/lib/arm, /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk!/lib/armeabi, /system/lib, /vendor/lib]]
at android.app.LoadedApk.makeApplication(LoadedApk.java:993)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5801)
at android.app.ActivityThread.-wrap1(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6650)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.tencent.sigma.patch.HotPatchApplication" on path: DexPathList[[zip file "/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk"],nativeLibraryDirectories=[/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/lib/arm, /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk!/lib/armeabi, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.Instrumentation.newApplication(Instrumentation.java:1088)
at android.app.LoadedApk.makeApplication(LoadedApk.java:987)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5801) 
at android.app.ActivityThread.-wrap1(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:173) 
at android.app.ActivityThread.main(ActivityThread.java:6650) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818) 
Suppressed: java.io.IOException: Failed to open dex files from /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk because: Failure to verify dex file '/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk': Out-of-order annotation_element name_idx: 7150 then 7150
at dalvik.system.DexFile.openDexFileNative(Native Method)
at dalvik.system.DexFile.openDexFile(DexFile.java:353)
at dalvik.system.DexFile.<init>(DexFile.java:100)
at dalvik.system.DexFile.<init>(DexFile.java:74)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:374)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:337)
at dalvik.system.DexPathList.<init>(DexPathList.java:157)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65)
at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64)
at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73)
at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88)
at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:69)
at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:35)
at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:695)
at android.app.LoadedApk.getClassLoader(LoadedApk.java:729)
at android.app.LoadedApk.getResources(LoadedApk.java:956)
at android.app.ContextImpl.createAppContext(ContextImpl.java:2282)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5723)
... 8 more

乍一看,以为是HotPatchApplication被混淆的原因导致Class Not Found,于是尝试keep住HotPatchApplication这个类,但是发现问题依旧。于是又怀疑是前不久升级gradle对分包造成了影响,对apk中的dex文件进行分析,发现HotPatchApplication这个类稳稳的躺在第一个dex文件中。

后来又进行了以下的尝试:

​ 1.尝试按顺序更改Kotlin版本,最后,当Kotlin版本为1.3.0时,发现问题出现了。

​ 2.另一个线索是当我打开Proguard时,那就是minifyEnable true,崩溃就出现了。

经过以上排查,基本确定了问题出在Kotlin和混淆的身上。最后发现上述日志中有一行:

1
Suppressed: java.io.IOException: Failed to open dex files from /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk because: Failure to verify dex file '/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk': Out-of-order annotation_element name_idx: 7150 then 7150

这个报错是第一次见到,上网搜了下,最终定位在混淆时的一个参数身上:-overloadaggressively

ProGuard官网解释:

-overloadaggressively Specifies to apply aggressive overloading while obfuscating. Multiple fields and methods can then get the same names, as long as their arguments and return types are different, as required by Java bytecode (not just their arguments, as required by the Java language). This option can make the processed code even smaller (and less comprehensible). Only applicable when obfuscating.

可以看出,开启该选项可能把不同的方法或者变量混淆成相同的名字,这样会尽可能的减小代码体积。但是由于过于激进,造成了dex文件中有重复annotation_element,这个问题在编译和打包时并不会报错,只有在开启软件时才会发现。

至于为什么升级了Kotlin才有这个问题,猜测原因是新版本的kotlin中加入了Keep注释与Java的Keep注释同名造成的。

解决办法:

去掉混淆文件(proguard.txt)中的-overloadaggressively

参考:

https://stackoverflow.com/questions/56458360/app-crashed-when-r8-enabled-with-existing-proguard-settings

https://issuetracker.google.com/issues/129241209#comment11

https://stackoverflow.com/questions/51948250/failure-to-verify-dex-file-out-of-order-annotation-element-name-idx

Author

calvinche

Posted on

2019-06-10

Licensed under

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×