Gradle原生依赖锁定需同时满足启用机制、生成提交gradle.lockfile、禁用动态版本三条件;须在settings.gradle(.kts)中声明lockAllConfigurations()并配合gradle.properties设org.gradle.dependency-locking.enabled=true,多模块项目需逐模块执行./gradlew :module:dependencies --write-locks,且必须设ignoreFailures=false确保严格校验。

Gradle 原生支持依赖锁定,不需要插件,但必须同时满足三个条件:启用锁定机制、生成并提交 gradle.lockfile、禁用动态版本。缺一不可,否则构建时看似正常,实则完全不生效。
怎么启用 dependencyLocking 并确保全局生效
只在 settings.gradle(或 settings.gradle.kts)里声明 lockAllConfigurations() 不够——如果项目有子模块但没显式 include,或者某个模块用了自定义配置(比如 androidTestImplementation),它可能被跳过。务必确认每个参与构建的模块都受控。
- Groovy 写法(
settings.gradle):dependencyLocking { lockAllConfigurations() } - Kotlin DSL(
settings.gradle.kts):dependencyLocking { lockAllConfigurations() } - 更稳妥的做法是配合
gradle.properties显式开启:org.gradle.dependency-locking.enabled=true,避免因脚本加载顺序导致未生效
生成 lockfile 的正确命令和路径陷阱
./gradlew dependencies --write-locks 看似简单,但实际行为取决于当前工作目录和 Gradle 版本。它不会递归扫描所有子模块,而是只处理当前 project 下可解析的配置。常见错误是:在根目录执行后,子模块目录下没生成 gradle.lockfile,CI 构建直接失败。
- 多模块项目必须逐个进入子模块目录执行,或使用前缀:
./gradlew :app:dependencies --write-locks - 锁文件默认生成在各模块根目录,不是统一放在
gradle/下;提交时容易漏掉某个子模块的gradle.lockfile - 首次生成后,若改了
build.gradle中的依赖,必须重新运行该命令,否则下次构建仍用旧锁,不会自动更新
为什么加了锁还报 NoClassDefFoundError
最常被忽略的是动态版本和传递依赖冲突。即使启用了 locking,只要存在 1.2.+、latest.release 或 + 这类写法,Gradle 会直接拒绝生成锁文件,并抛出明确错误:Dependency locking is not supported for dynamic versions。但很多团队把 ignoreFailures=true 打开,让构建“强行通过”,结果锁文件根本没写入,整个机制形同虚设。
- 检查所有
implementation、api、testImplementation等语句,包括buildSrc和plugins块里的依赖 - 支付宝 SDK 等 AAR 依赖若用
@aar后缀,要确认其 POM 是否含动态版本的传递依赖,必要时用exclude排除 -
org.gradle.dependency-locking.ignoreFailures=false必须显式设置,不能依赖默认值——某些 CI 环境会覆盖 gradle.properties
真正起作用的从来不是“有没有锁文件”,而是每次构建是否强制校验锁与当前依赖树的一致性。一旦允许绕过(比如 ignoreFailures=true 或本地改了依赖却不重写锁),锁定就退化成装饰品。多模块项目里,一个模块漏锁,整条构建链的确定性就崩了。











