1. 简介
本文将深入探讨如何通过 Gradle 执行 Java 的 main
方法。这是日常开发中非常常见的需求,比如运行测试程序、启动脚本或调试工具类。掌握几种不同的实现方式,能让你在不同场景下更灵活地选择方案,避免踩坑。
2. Java main 方法示例
我们先准备一个简单的 Java 类,用于演示各种运行方式:
public class MainClass {
public static void main(String[] args) {
System.out.println("Goodbye cruel world ...");
}
}
这个类只有一个 main
方法,输出一句话。接下来我们会用 Gradle 的多种方式来执行它。
3. 使用 Application 插件(推荐新手)
Gradle 提供了一个开箱即用的 Application 插件,专门用于构建和运行可执行的 Java 应用。它会自动生成 run
任务,配置简单,适合快速上手。
在 build.gradle
中添加以下配置:
plugins {
id "application"
}
apply plugin: "java"
ext {
javaMainClass = "com.baeldung.gradle.exec.MainClass"
}
application {
mainClassName = javaMainClass
}
✅ 说明:
plugins { id "application" }
启用插件mainClassName
指定入口类的全限定名(含包名)ext
块用于定义公共变量,便于复用
配置完成后,直接运行:
./gradlew run
输出结果:
> Task :run
Goodbye cruel world ...
BUILD SUCCESSFUL in 531ms
2 actionable tasks: 1 executed, 1 up-to-date
⚠️ 注意: mainClassName
已被标记为过时,新版本建议使用 mainClass.set(...)
,但兼容性尚可,老项目无需急着改。
4. 使用 JavaExec 任务(灵活可控)
如果你不想引入 Application 插件,或者需要更细粒度控制 JVM 参数、环境变量等,可以使用 JavaExec
任务类型。
自定义任务如下:
task runWithJavaExec(type: JavaExec) {
group = "Execution"
description = "Run the main class with JavaExecTask"
classpath = sourceSets.main.runtimeClasspath
main = javaMainClass
}
✅ 关键点:
type: JavaExec
表示这是一个 JVM 进程执行任务classpath
必须指定,通常使用sourceSets.main.runtimeClasspath
main
设置主类全限定名- 可扩展添加
jvmArgs
,args
,systemProperties
等
执行命令:
./gradlew runWithJavaExec
输出:
> Task :runWithJavaExec
Goodbye cruel world ...
BUILD SUCCESSFUL in 526ms
2 actionable tasks: 1 executed, 1 up-to-date
💡 适用场景:
- 需要传参给
main(String[] args)
- 调整堆内存、GC 参数
- 多个入口类切换运行
5. 使用 Exec 任务(底层控制)
Exec
是最底层的任务类型,直接调用操作系统命令。虽然灵活性最高,但也最易出错,需手动处理依赖和路径。
我们分三种情况来演示。
5.1. 从编译输出目录运行
先编译再执行 class 文件:
task runWithExec(type: Exec) {
dependsOn build
group = "Execution"
description = "Run the main class with ExecTask"
commandLine "java", "-classpath", sourceSets.main.runtimeClasspath.getAsPath(), javaMainClass
}
✅ 要点:
dependsOn build
确保先编译commandLine
构造完整的java -cp ...
命令getAsPath()
将 classpath 转为字符串
执行:
./gradlew runWithExec
输出正常,耗时略长(因为触发了完整构建)。
5.2. 从普通 Jar 文件运行
打包成 jar 后运行,需显式指定主类:
task runWithExecJarOnClassPath(type: Exec) {
dependsOn jar
group = "Execution"
description = "Run the mainClass from the output jar in classpath with ExecTask"
commandLine "java", "-classpath", jar.archiveFile.get(), javaMainClass
}
⚠️ 注意:
jar.archiveFile.get()
获取 jar 文件路径- 依然是
-classpath
加主类方式,不是-jar
- 适用于没有设置
Main-Class
的 jar
执行成功后输出相同。
5.3. 从可执行 Jar 运行
生成带 Main-Class
的可执行 jar:
jar {
manifest {
attributes(
"Main-Class": javaMainClass
)
}
}
task runWithExecJarExecutable(type: Exec) {
dependsOn jar
group = "Execution"
description = "Run the output executable jar with ExecTask"
commandLine "java", "-jar", jar.archiveFile.get()
}
✅ 优势:
- 不需要指定 classpath
- 命令简洁,符合生产部署习惯
manifest
中定义入口点
执行:
./gradlew runWithExecJarExecutable
输出一致,且命令更干净。
6. 总结与选型建议
方式 | 优点 | 缺点 | 推荐场景 |
---|---|---|---|
✅ Application 插件 | 配置简单,开箱即用 | 灵活性低 | 快速原型、学习项目 |
✅ JavaExec | 控制精细,无需插件 | 需手动配置 classpath | 需要传参、调 JVM 参数 |
⚠️ Exec | 完全自由,可执行任意命令 | 易出错,维护成本高 | 特殊集成、脚本化部署 |
📌 最终建议:
- 日常开发首选 JavaExec,简单粗暴又灵活
- 团队项目可用 Application 插件,统一规范
Exec
仅在必要时使用,比如要调外部脚本或特殊启动逻辑
示例代码已整理至 GitHub:https://github.com/baeldung/tutorials/tree/master/gradle-modules/gradle-5