Gradle默认不报错是因为采用“最高版本胜出”策略,静默选择高版本(如2.15.0)导致运行时NoSuchMethodError;strictly强制版本一致并立即报错,failOnVersionConflict()则全局禁止版本漂移。

Gradle 版本冲突默认不报错,为什么?
Gradle 默认采用“最高版本胜出”策略,遇到 com.fasterxml.jackson.core:jackson-databind 同时被要求 2.13.0 和 2.15.0 时,它会静默选 2.15.0,并继续构建。这种“自动兜底”看似省事,实则埋下隐患:比如某个库内部调用了 2.13.0 特有的私有方法,运行时直接 NoSuchMethodError —— 构建成功了,上线就崩。
用 strictly 让冲突立刻暴露
在依赖声明中显式加 version { strictly '2.14.2' },Gradle 就会在解析阶段检测到任何偏离该版本的请求(无论来自直接还是传递依赖),并立即中断构建,抛出清晰错误:
Could not resolve all dependencies for configuration ':app:runtimeClasspath'.
Conflict(s) found for dependency 'com.fasterxml.jackson.core:jackson-databind':
- Required by:
project :app
- Found in:
com.google.guava:guava:32.1.3-jre → com.fasterxml.jackson.core:jackson-databind:2.15.0
org.apache.beam:beam-runners-direct-java:2.47.0 → com.fasterxml.jackson.core:jackson-databind:2.14.1
- Declared as strictly '2.14.2'
此时你必须手动处理冲突,而不是靠 Gradle “猜”一个版本。
-
strictly必须写在依赖块内,不能只写force; - 它对传递依赖也生效,但仅限于该依赖子图;
- 多个
strictly声明同一坐标不同版本会直接构建失败,不妥协; - 适用于关键基础库(如
jackson-databind、guava、okhttp);
全局启用严格模式:failOnVersionConflict()
在 build.gradle 的 configurations.all 块里加这一行,能让整个项目所有配置都拒绝版本漂移:
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
效果比单个 strictly 更彻底,但代价是:只要依赖图里有任何未对齐,构建立刻终止。适合 CI 环境或强治理阶段使用。
- 它不指定具体版本,只强制“全图一致”,仍需配合
force或 BOM 来落地版本; - 和
strictly不冲突,可共存; - 本地开发时建议先关掉,避免频繁打断;
为什么不用 force 替代 strictly?
force 是“我指定谁上”,strictly 是“只准这个上,别的都不行”。区别很关键:
-
force '2.14.2'会让 Gradle 把所有路径都拉到 2.14.2,哪怕某库根本没测试过这个版本,运行时可能炸; -
strictly '2.14.2'则先检查:如果某个传递依赖硬性要求 2.15.0(比如用到了新 API),构建就停住,逼你去查那个库是否可升级或能否排除; -
force容易掩盖兼容性问题,strictly强制你直面依赖契约;
真正要防线上事故,得让冲突在构建期就卡死,而不是靠运气选个“看起来能跑”的版本。











