上一篇
在Java中创建新进程主要通过
Runtime.exec()或
ProcessBuilder类实现,后者更推荐,提供进程环境控制、重定向输入输出流等功能,
Process process = new ProcessBuilder("命令").start(); 需注意异常处理和资源释放。
在Java中创建新进程是一项强大的功能,允许程序执行外部命令或启动其他应用程序,Java提供了两种核心方式:Runtime.exec() 和 ProcessBuilder,以下将详细解析这两种方法,包括代码示例、最佳实践及安全注意事项。
使用 Runtime.exec() 创建进程
Runtime 类是Java早期版本的标准方法,通过调用系统命令启动进程。

代码示例:
try {
// 执行系统命令(Windows示例:启动记事本)
Process process = Runtime.getRuntime().exec("notepad.exe");
// 等待进程结束(可选)
int exitCode = process.waitFor();
System.out.println("进程退出码: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
关键说明:
- 命令格式:直接传入字符串形式的命令(如
"ping baidu.com")。 - 阻塞控制:
waitFor()会阻塞当前线程直至进程结束。 - 资源释放:务必通过
process.destroy()或process.destroyForcibly()主动终止进程,避免资源泄漏。
使用 ProcessBuilder 创建进程(推荐)
ProcessBuilder 是更灵活、安全的替代方案,支持参数列表、环境变量和重定向控制。
代码示例:
try {
// 构建命令及参数(Linux/macOS示例:列出目录)
ProcessBuilder builder = new ProcessBuilder("ls", "-l", "/home");
// 重定向错误流到标准输出(可选)
builder.redirectErrorStream(true);
// 启动进程
Process process = builder.start();
// 读取进程输出
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 获取退出码
int exitCode = process.waitFor();
System.out.println("退出码: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
优势特性:
- 参数安全拆分:避免手动处理空格和引号,防止命令注入破绽。
- 重定向灵活:
redirectOutput(File):输出到文件redirectInput(File):从文件读取输入
- 环境变量控制:
builder.environment().put("PATH", "/custom/path");
两种方式对比
| 特性 | Runtime.exec() |
ProcessBuilder |
|---|---|---|
| 参数安全性 | 低(需手动处理字符串) | 高(参数列表自动处理) |
| 重定向支持 | 有限 | 完善(文件/流/继承) |
| 环境变量控制 | 不支持 | 支持 |
| 适用场景 | 简单命令 | 复杂进程管理 |
安全与异常处理要点
-
命令注入防御:

- 避免拼接用户输入作为命令(如
Runtime.getRuntime().exec("cmd " + userInput))。 - 使用
ProcessBuilder的参数列表机制自动转义。
- 避免拼接用户输入作为命令(如
-
流处理:
- 必须读取进程的输出/错误流,否则可能导致进程阻塞(缓冲区满)。
- 示例:通过独立线程消费流:
new Thread(() -> { try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { while (reader.readLine() != null); } catch (IOException ignored) {} }).start();
-
超时控制:
if (!process.waitFor(30, TimeUnit.SECONDS)) { process.destroyForcibly(); // 超时强制终止 }
典型应用场景
- 调用系统工具(如压缩、编译)。
- 执行Python/Shell脚本。
- 启动其他Java程序(通过
java -jar)。
- 简单命令:优先选
Runtime.exec()(需注意参数安全)。 - 复杂需求:务必使用
ProcessBuilder(参数控制、重定向、环境变量)。 - 通用规范:
- 始终处理输入/输出流。
- 添加超时和销毁逻辑。
- 避免阻塞主线程。
引用说明基于Oracle官方文档 《ProcessBuilder》 和 《Runtime》,并结合Java安全编程实践编写。

