在java的exec上关闭流的正确方法是啥?

Posted

技术标签:

【中文标题】在java的exec上关闭流的正确方法是啥?【英文标题】:what is the proper way to close streams on java's exec?在java的exec上关闭流的正确方法是什么? 【发布时间】:2021-09-28 21:32:26 【问题描述】:

之后

Runtime.getRuntime().exec(command);

我看到系统调用显示 2~3 个文件描述符(FIFO 管道)。使用 try-with-resource 模式关闭它们的正确方法是什么?

在 java 论坛上发现的大多数历史部落知识表明:

# out of date!
...  finally 
            IOUtils.closeQuietly(p.getOutputStream());
            IOUtils.closeQuietly(p.getInputStream());
            IOUtils.closeQuietly(p.getErrorStream());

但这听起来不对,因为 1) 方法 closeQuietly 已弃用,大多数库建议使用 try-with-resource,2) 它不优雅,因为我可能不一定拥有所有流。 简单地将 exec() 调用移到 try 中感觉不对,因为它不是我将调用 close() 的资源。

【问题讨论】:

如果您除了打印它们之外没有对这些流做任何事情,您可以使用 ProcessBuilder 而不是 Runtime.exec,并调用 ProcessBuilder 的 inheritIO() 方法。那么根本不需要管理这些流。 【参考方案1】:

没有必要关闭它们;当进程死亡时,它们自己关闭。如果进程永远不会死,它也不是必需的:要么你经常创建一个新的永不消亡的进程,在这种情况下,无论你是否关闭它们,你的系统都会崩溃并耗尽资源,或者你只创建它一次,在这种情况下,这些资源不会很重要。值得一提的是,这些资源是相当轻量级的资源,并且通常它们根本无法“关闭”,因为资源可以“释放”——关闭它们要么使它们保持打开状态,但会拒绝进一步聊天(并在需要的地方发送 EOF),或者将它们重新路由到 /dev/null;通常进程在 em 上只有 3 个管道,并且会继续拥有它们,直到进程终止。

是的,closeQuietly 对于几乎所有目的来说都是一个愚蠢的想法,所以它就在这里。如果关闭这些流以某种方式失败,您可能不想默默地忽略它。

如果您必须关闭它们,则这 3 个中的各个流都是可关闭的。但是,请注意,您正在阅读经验法则并试图将它们当作福音真理来应用。 try-with-resources 并不总是正确的答案,try-with-resources 也不是 100% 总是替代 close,更不用说 closeQuietly。

例如,try-with-resources 是专门针对一段时间的使用而设计的。您声明资源应该可用的语句范围(与try 块一起使用的大括号),然后该构造将确保仅在代码流转换出该语句范围时才关闭资源,不不管它如何退出。 这也让它在这里可能无关紧要!

    您正在开始一个长期的过程,并不关心输入/输出。您只希望进程运行并继续运行。这意味着根本没有跨度,如果您觉得尝试保存资源很重要,即使这很可能根本没有任何效果,您应该在这些上调用close()。没有跨度语句意味着 try-with-resources 是不正确的。

    您正在启动一个与之交互的短暂过程。 “关闭”的正确方法是流程本身,但您不能为此使用 try-with-resources。这只能用于自动关闭。 (代表它们的类实现 AutoClosable 的资源。大多数会,有些不会。锁是一个著名的。进程是另一个:要“关闭”它,你调用destroy() 甚至destroyForcibly()。你不能使用 try-with-resources(不是没有破坏目的的丑陋黑客)来做到这一点!一旦你关闭/销毁进程,随之而来的流也死了。

    更一般的原则是:如果你创建它,你就关闭它。如果你从不打电话给getOutputStream(),你就永远不会创建它们。在某些操作系统上,获取这些流然后关闭它们比不这样做浪费更多的资源。因此,如果论点是基于某种纯度模型,那么您也不应该关闭它们。如果它基于语用学,您必须测试这些资源的实际重量(很可能,非常轻),关闭它们是否真的可以节省一些管道(很可能不会),以及close()-ing在进程中调用getOutputStream() 的结果甚至有助于如果上述问题的答案使其相关(它可能会,但规范不保证这一点)。

【讨论】:

【参考方案2】:

它们是非常轻量级的进程,几乎在所有情况下都不需要关闭...

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于在java的exec上关闭流的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

JPA常用的关闭流的方式是啥?事务管理?还是手动关闭?

关闭和清理 Socket 连接的正确方法是啥?

为 Qt 工作线程打开和关闭数据库连接的正确方法是啥

使用情节提要时关闭模式的正确方法是啥?

关闭H2的正确方法是啥?

在java A-Z中学习安全性的最佳方法是啥[关闭]