1. 使用 ProcessBuilder
类
Kotlin 作为 JVM 上的语言,天然支持 Java 的标准类库,我们可以通过 ProcessBuilder
类来调用外部命令。这是目前推荐的方式之一,因为它提供了更灵活、可控的 API。
我们来看一个简单的例子,执行 java -version
命令并验证执行结果:
@Test
fun `Given a command, When executed with ProcessBuilder, Then it is executed successfully`() {
val result = ProcessBuilder("java", "-version")
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()
.waitFor()
assertThat(result).isEqualTo(0)
}
✅ 说明:
- 使用
ProcessBuilder
构造命令参数时,建议使用多个字符串参数,避免命令注入等潜在问题 redirectOutput(...)
和redirectError(...)
设置为INHERIT
表示输出和错误信息会直接输出到当前进程的控制台,方便调试start()
启动进程,waitFor()
等待执行完成并返回退出码(0 表示成功)
⚠️ 踩坑提示:
在 Windows 上执行命令时,可能需要显式调用 cmd /c
来执行脚本,例如:
ProcessBuilder("cmd.exe", "/c", "echo", "Hello World")
2. 使用 Runtime
类
虽然 Runtime
类也可以执行外部命令,但其 API 相对简单,功能也有限。
@Test
fun `Given a command, When executed with Runtime, Then it is executed successfully`() {
val process = Runtime.getRuntime().exec("java -version")
val result = process.waitFor()
assertThat(result).isEqualTo(0)
}
⚠️ 踩坑提示:
Runtime.exec(String)
方法从 JDK 18 开始被标记为 废弃(deprecated)- 建议改用
exec(String[])
或exec(String... command)
形式,避免命令解析错误或安全问题
✅ 推荐写法:
val process = Runtime.getRuntime().exec(arrayOf("java", "-version"))
❌ 不推荐写法(已废弃):
val process = Runtime.getRuntime().exec("java -version") // 不推荐
3. 小结与建议
方法 | 是否推荐 | 特点说明 |
---|---|---|
ProcessBuilder |
✅ 推荐 | 更灵活、支持重定向、跨平台兼容性好 |
Runtime.exec() |
❌ 不推荐 | API 简单、功能有限,且已被废弃 |
总结:
- 如果你需要执行外部命令并控制其输入输出、环境变量等行为,强烈建议使用
ProcessBuilder
- 避免使用
Runtime.exec(String)
,因为它不仅被废弃,还容易因命令解析不当导致安全问题或运行时异常
完整示例代码可参考:GitHub 示例仓库