Shadow Guava时D8因minSdk版本报错的原因及解决方案
问题
开发公共库时需要通过Shadow方式隔离依赖,避免使用者出现依赖冲突。直接引入Guava无问题,但Shadow后触发D8报错,提示MethodHandle.invoke和MethodHandle.invokeExact仅支持Android O(minSdk26及以上),但项目minSdk为16且无法升级。
主项目build.gradle.kts配置:
plugins { id("com.android.library") } android { namespace = "my.namespace" compileSdk = 34 defaultConfig { minSdk = 16 } } dependencies { implementation(project(path = ":Shadow-Module", configuration = "shadow")) }
Shadow-Module的build.gradle.kts配置:
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id("java") id("com.github.johnrengelman.shadow") version "8.1.1" } val shadowJar = tasks.named<ShadowJar>("shadowJar") { isEnableRelocation = true relocationPrefix = "my.namespace.shadow" } dependencies { implementation("com.google.guava:guava:33.1.0-android") }
报错信息:
AGPBI: {"kind":"error","text":"MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26): Lmy/namespace/shadow/com/google/common/hash/Hashing$Crc32cMethodHandles;newCrc32c()Ljava/util/zip/Checksum;","sources":[{"file":"~/.gradle/caches/transforms-4/ddfd1a8942a2e6d1a88e6eb87139afdd/transformed/jetified-Shadow-Module-all.jar"}],"tool":"D8"} FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':My-SDK:mergeDexAppDebugAndroidTest'. > Could not resolve all files for configuration ':My-SDK:appDebugAndroidTestRuntimeClasspath'. > Failed to transform Shadow-Modules-all.jar (project :Shadow-Modules) to match attributes {artifactType=android-dex, dexing-component-attributes=ComponentSpecificParameters(minSdkVersion=16, debuggable=true, enableCoreLibraryDesugaring=false, enableGlobalSynthetics=false, enableApiModeling=false, dependenciesClassesAreInstrumented=false, asmTransformComponent=null, useJacocoTransformInstrumentation=false, enableDesugaring=true, needsClasspath=true, useFullClasspath=false, componentIfUsingFullClasspath=null), org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}. > Execution failed for DexingWithClasspathTransform: ~/.gradle/caches/transforms-4/ddfd1a8942a2e6d1a88e6eb87139afdd/transformed/jetified-Shadow-Module-all.jar. > Error while dexing. Increase the minSdkVersion to 26 or above.
原因分析
- 直接引入Guava的适配逻辑:Guava的Android专属版本(
guava:xx.x.x-android)内置了低版本适配机制,AGP在处理直接依赖时,会根据项目minSdk自动筛选兼容的实现类,跳过MethodHandle这类仅支持高API的代码。 - Shadow插件的处理缺陷:Shadow插件基于Java插件构建,仅负责重新打包并 relocate 类路径,不会识别Android的minSdk适配规则。这导致Guava中原本仅为高版本Android准备的
MethodHandle相关实现类被一并打包进Shadow jar,D8处理时检测到高API调用,触发报错。
解决方案
方式一:在Shadow模块启用Core Library Desugaring
Core Library Desugaring可让低版本Android支持Java 8+的API,包括MethodHandle。需将Shadow模块从Java插件切换为Android Library插件,启用Desugaring:
修改Shadow-Module的build.gradle.kts:
plugins { id("com.android.library") id("com.github.johnrengelman.shadow") version "8.1.1" } android { namespace = "my.namespace.shadow" compileSdk = 34 defaultConfig { minSdk = 16 } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 coreLibraryDesugaringEnabled = true } } val shadowJar = tasks.named<ShadowJar>("shadowJar") { isEnableRelocation = true relocationPrefix = "my.namespace.shadow" } dependencies { implementation("com.google.guava:guava:33.1.0-android") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4") }
方式二:排除Guava中含MethodHandle的类
通过Shadow插件配置,直接排除包含高API调用的类,仅保留低版本兼容实现:
修改Shadow-Module的shadowJar任务配置:
val shadowJar = tasks.named<ShadowJar>("shadowJar") { isEnableRelocation = true relocationPrefix = "my.namespace.shadow" // 排除使用MethodHandle的Crc32c实现类 exclude("com/google/common/hash/Hashing\$Crc32cMethodHandles.class") // 若有其他报错,可补充排除对应类 }
注意:此方法仅适用于业务未用到被排除类的场景,若需使用相关功能,优先选择方式一。
内容的提问来源于stack exchange,提问作者Hounshell
相关产品推荐
相关产品推荐

