Java调用Runtime.exec后如何用try-with-resource正确关闭流?
正确实现方案
Runtime.getRuntime().exec()返回的Process对象持有的三个管道流(标准输入OutputStream、标准输出InputStream、标准错误InputStream)均实现了AutoCloseable接口,完全可以直接放入try-with-resource的资源声明块中由JVM自动关闭,不需要手动写关闭逻辑。
通用写法(兼容Java 8及以上版本)
Process process = Runtime.getRuntime().exec("your command here"); // 仅声明你实际需要用到的流即可,不需要的可以不用声明,也可以提前手动关闭 try ( OutputStream stdin = process.getOutputStream(); InputStream stdout = process.getInputStream(); InputStream stderr = process.getErrorStream() ) { // 此处编写业务逻辑:比如向进程写入输入、读取输出/错误流内容等 // ... } finally { // 等待进程执行结束获取退出码,可选按需添加 int exitCode = process.waitFor(); // 销毁进程避免残留 process.destroy(); }
简化场景写法(仅用到部分流)
如果你的场景不需要操作全部三个流,只需要声明用到的流即可,没用的流可以直接提前关闭避免资源泄漏:
Process process = Runtime.getRuntime().exec("your command here"); // 提前关闭不需要的流 process.getOutputStream().close(); process.getErrorStream().close(); // 只声明需要用到的标准输出流 try (InputStream stdout = process.getInputStream()) { // 读取标准输出逻辑 // ... } finally { process.waitFor(); process.destroy(); }
方案优势
- 完全符合JDK官方推荐的资源管理规范,不需要依赖第三方类库的废弃方法
- 编译器会自动生成所有声明资源的关闭逻辑,即使业务代码抛出异常也不会漏关,不会出现文件描述符泄漏
- 写法灵活,用几个流就声明几个,不需要冗余代码
- 适配Java 8及以上所有版本,低版本环境也能正常运行
注意事项
Java 9及以上版本虽然Process实现了AutoCloseable接口,但关闭进程只会调用destroy()销毁进程,不会自动关闭关联的三个流,因此流还是需要单独放入try-with-resource块中管理。不要直接把exec()调用放入try-with-resource的资源声明块中,一是低版本Java不支持Process作为资源,二是即使高版本支持也不会自动关流,还是会有资源泄漏风险。
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

