如何让Gradle优先使用APK中Apache Commons Lang3解决NoSuchMethodError?
解决Android系统与应用Apache Commons Lang3版本冲突问题
这个问题我之前帮好几个开发者解决过——确实是系统自带的旧版Apache Commons Lang3和你应用里依赖的新版本撞车了!Android系统框架里的旧版本库没有decrementAndGet()这个方法,而系统类加载器会优先加载系统提供的类,导致你的代码调用这个方法时抛出NoSuchMethodError。
要强制使用你APK里的新版本,不能只靠Gradle的force参数(因为系统类加载优先级更高),最可靠的方式是通过重命名依赖包的方式,让你的代码引用专属的包名,避开系统类的冲突。具体步骤如下:
1. 引入Shadow Gradle插件
Shadow插件可以帮你重命名依赖库的包名,把Apache Commons Lang3的代码打包到你自定义的包路径下。
首先在项目根目录的build.gradle(Project级)中添加插件依赖:
buildscript { repositories { mavenCentral() } dependencies { // 建议使用最新版本的Shadow插件 classpath 'com.github.johnrengelman.shadow:7.1.2' } }
2. 配置App模块的Shadow插件
在App模块的build.gradle(Module级)中应用插件,并配置包名重定向:
plugins { id 'com.android.application' id 'com.github.johnrengelman.shadow' } android { // 保留你原有的Android配置(compileSdk、defaultConfig等) } // 配置Shadow插件,将原包名重定向到你自定义的包路径 shadowJar { // 把org.apache.commons.lang3重命名为你自己的包前缀,比如com.yourapp.commons.lang3 relocate 'org.apache.commons.lang3', 'com.yourapp.commons.lang3' } // 确保构建APK时自动执行Shadow打包任务 tasks.withType(com.android.build.gradle.tasks.PackageApplication) { dependsOn shadowJar }
3. 修改代码中的导入语句
重命名包之后,你代码里所有引用Apache Commons Lang3的地方,都要把导入路径改成你自定义的包名。比如:
原来的:
import org.apache.commons.lang3.mutable.MutableInt;
改成:
import com.yourapp.commons.lang3.mutable.MutableInt;
为什么不用force参数?
很多人会尝试用implementation('org.apache.commons:commons-lang3:3.12.0') { force = true }来强制依赖版本,但这没用——因为Android的类加载机制是优先加载系统框架中的类,再加载APK里的类。即使你强制了版本,系统的旧版类还是会被先加载,导致方法找不到。
内容的提问来源于stack exchange,提问作者Minas Mina
相关产品推荐
相关产品推荐

