升级Gradle至4.1.1后Android 4设备出现java.lang.VerifyError求助
java.lang.VerifyError 从你的描述来看,在将Gradle从6.1.1+AGP4.0.1升级到6.5+AGP4.1.1后,Android 4(Dalvik虚拟机)设备出现了VerifyError,这个问题在Dalvik环境下非常典型,主要和字节码兼容性、编译优化以及AndroidX库适配有关,下面是具体的分析和解决思路:
核心原因
Android 4.x使用的Dalvik虚拟机对Java字节码的兼容性远不如后续的ART虚拟机,而AGP 4.1.x和Gradle 6.5的组合,默认的编译配置、字节码处理逻辑有变化,可能引入了Dalvik无法识别的字节码特性(比如Java 8的默认接口方法、静态接口方法等),或者R8优化后的字节码触发了Dalvik的验证规则。
具体解决方案
1. 确保Java 8特性的Desugar配置正确
AGP 4.1.x对Java 8的支持更完善,但如果你的项目使用了Java 8特性(哪怕是间接依赖的AndroidX库使用了),必须明确开启Desugar转换,否则Dalvik无法识别这些字节码:
在模块的build.gradle中添加如下配置:
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } // 如果是Kotlin项目,还要添加Kotlin的JVM目标配置 kotlinOptions { jvmTarget = "1.8" } }
Desugar会将Java 8的字节码转换为Dalvik兼容的版本,这是解决这类VerifyError最常见的手段。
2. 检查AndroidX Fragment库版本兼容性
AGP版本和AndroidX库版本需要匹配,AGP 4.1.1对应的AndroidX Fragment建议使用1.3.0及以上版本(可以在项目的build.gradle中明确指定):
dependencies { implementation 'androidx.fragment:fragment:1.3.6' implementation 'androidx.fragment:fragment-ktx:1.3.6' // Kotlin项目可选 }
旧版本的Fragment库可能和新AGP编译出的字节码存在兼容性问题,升级到适配AGP 4.1的版本可以解决这类初始化时的错误。
3. 排查R8优化导致的问题
AGP 4.1.x默认启用R8作为代码压缩工具,R8的某些优化可能生成了Dalvik无法通过验证的字节码。可以先临时关闭R8验证是否是这个原因:
在项目根目录的gradle.properties中添加:
android.enableR8=false
如果关闭后问题消失,说明需要添加针对AndroidX Fragment的R8规则,避免关键类被错误优化:
# 保留Fragment相关类的完整结构,避免Dalvik验证失败 -keep class androidx.fragment.app.** { *; } -keep class androidx.fragment.app.FragmentHostCallback { *; } -keep class androidx.fragment.app.FragmentActivity$HostCallbacks { *; }
之后可以逐步调整规则,找到最小必要的保留项,避免过度保留代码。
4. 检查是否存在多Dex的兼容性问题
如果你的项目启用了多Dex,Android 4.x设备上的多Dex初始化可能存在问题,确保MultiDexApplication配置正确:
- 继承
MultiDexApplication,或者在Application的attachBaseContext中调用MultiDex.install(this) - 确保
multidexEnabled true在build.gradle的android.defaultConfig中配置
总结
这类问题本质是Dalvik和ART虚拟机的字节码差异导致的,优先通过配置Desugar、匹配AndroidX库版本来解决,再排查R8和多Dex的影响,基本可以覆盖绝大多数场景。
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

