讲师中心 微信公众号
AI工具推荐 视频效率加速

Gradle compileOnly和runtimeOnly怎么选

阿敏小哥_1166

阿敏小哥_1166

发布时间:2026-10-28 13:44:05

|

119人浏览过

|

来源于php中文网

原创

compileOnly仅用于编译期需类但运行时由宿主提供(如注解、SDK接口),误用于new实例或直接调用会导致NoClassDefFoundError;其安全前提为所有引用均通过反射+兜底逻辑处理。

gradle compileonly和runtimeonly怎么选

compileOnly 什么时候用,又为什么容易崩溃

当你写的模块(比如一个 SDK 或工具库)在编译时需要某个类(比如 javax.annotation.Nullable 或 androidx.annotation.NonNull),但运行时完全不依赖它——或者更关键的是:**这个类由宿主 App 在运行时提供**,才该用 compileOnly。

常见误用是把 compileOnly 当成“轻量版 implementation”,比如给一个网络库加 compileOnly 'com.squareup.okhttp3:okhttp:4.12.0',结果一运行就抛 NoClassDefFoundError。因为 Gradle 根本没打包 OkHttp,而你的代码又直接 new 了 OkHttpClient,这属于编译可见、运行不可见的硬伤。

  • ✅ 正确场景:写一个注解处理器兼容库,依赖 com.google.auto.service:auto-service:1.1.1,但只在编译期生成代码,不参与运行
  • ✅ 正确场景:Android 库中引用 androidx.lifecycle:lifecycle-common:2.7.0 的注解,但生命周期逻辑由 App 自己引入实现
  • ❌ 错误场景:任何你代码里显式调用、new 实例、或反射加载的类,只要没被宿主 App 显式声明为 runtime 依赖,就不能靠 compileOnly

runtimeOnly 基本没人真用,除非你明确控制 classpath

runtimeOnly 表示:编译时看不到这个依赖,但会打进 APK/AAR/JAR 里,留给运行时加载。听起来像“隐藏依赖”,但实际落地极难——因为你无法在编译期引用它的任何类,连 import 都会报错。

这意味着你只能通过反射、SPI、或 ClassLoader.loadClass 动态加载它。而 Android 上 runtimeOnly 打包进 APK 后,ART 运行时默认能加载;但在 Java Web 或 Spring Boot 场景下,如果没手动把它加进 ClassLoader 或 spring.factories,照样找不到类。

  • ⚠️ 它不是“懒加载开关”,而是彻底切断编译期链接能力
  • ⚠️ 它和 apk(已弃用配置)行为一致,Gradle 官方文档里几乎不提使用案例
  • ? 极少数可行场景:插件化框架中,主壳工程预埋一个空接口,插件模块用 runtimeOnly 提供具体实现 JAR,再由壳动态加载

implementation 和 api 才是日常主力,compileOnly/runtimeOnly 是边界特例

绝大多数业务模块、App 模块、甚至普通 Library,都不该优先考虑 compileOnly 或 runtimeOnly。它们的存在意义是解决特定耦合问题,不是通用替代方案。

比如你写一个封装了 Gson 的 JSON 工具类,内部用了 Gson 和 TypeToken,那必须用 implementation 'com.google.code.gson:gson:2.10.1'——哪怕下游模块也想用 Gson,也应该自己声明,而不是靠你“泄露”过去。

  • 用 api 的唯一合理理由:你暴露的 public 方法签名里直接用了该依赖的类型(例如返回 Call<response></response>,就必须 api 'com.squareup.retrofit2:retrofit:2.9.0')
  • compileOnly 的安全前提:你所有对该依赖的引用都包裹在 try/catch (ClassNotFoundException) 或 Class.forName(...).isPresent() 里,并有 fallback 行为
  • runtimeOnly 的安全前提:你从不 import、不 new、不写泛型约束、不参与编译期类型推导——只靠字符串类名 + 反射活下来

最容易被忽略的点:transitive 和 exclude 的组合影响

compileOnly 和 runtimeOnly 都默认关闭传递依赖(transitive = false)。但如果你手动写了 compileOnly('xxx') { transitive = true },就可能意外带入一堆编译期不需要、运行时又缺失的间接依赖,导致构建成功但运行失败。

反过来,runtimeOnly 如果依赖了一个带 native 库的包(比如 net.java.dev.jna:jna:5.13.0),它虽然打进 APK,但 Android 不支持 JNA 的 so 加载机制,照样会 UnsatisfiedLinkError。

所以选配置之前,先跑一遍 ./gradlew app:dependencies --configuration runtimeOnlyClasspath 或 compileOnlyClasspath,确认实际解析出的依赖树是否符合预期——这才是真正卡住问题的地方。

热门AI工具

更多
小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

相关专题

更多
Java Maven/Gradle 构建与依赖管理合集
Java Maven/Gradle 构建与依赖管理合集

系统讲解 Java 项目构建工具的使用与进阶配置,涵盖 Maven 的 POM 文件结构、生命周期(clean/compile/package/install/deploy)与插件机制、依赖范围(compile/provided/test/runtime)与传递依赖管理、多模块聚合与继承、私有 Nexus 仓库发布,以及 Gradle 的 Groovy / Kotlin DSL 语法、Task 自定义与增量构建、依赖版本目录(Versi

389

2026.05.09

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

20

2026.10.28

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

40

2026.10.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

140

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

80

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

80

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

40

2026.10.22

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

80

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Gradle 9 主版本升级指南
Gradle 9 主版本升级指南

共0课时 | 0人学习

Gradle 安全最佳实践
Gradle 安全最佳实践

共0课时 | 0人学习

Gradle 依赖校验手册
Gradle 依赖校验手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn