【问题标题】:What happens to stderr/stdout streams after Process.destroy() in Java?在 Java 中 Process.destroy() 之后 stderr/stdout 流会发生什么?
【发布时间】:2022-04-11 21:29:31
【问题描述】:

我想为从 Java 启动的进程设置一个超时。超时后,我想终止该进程。到目前为止,一切都很好。问题是,我想在正常执行期间和超时后捕获标准错误/标准输出。如果我用 destroy() 杀死进程会发生什么?我可以检索到目前为止生成的(部分)stderr/stdout 吗?还是他们走了?

【问题讨论】:

  • 你如何阅读标准输出和标准错误?他们怎么会有“部分”输出?
  • 当进程超时我杀了它,会有部分结果。不过,我还是想把它们抓起来,以备日后调查。

标签: java process


【解决方案1】:

进程处理本质上是特定于操作系统的,我在这里专门研究 Java 如何处理 Unix 进程。

很不幸Process closes its streams when you call .destroy()。我不知道为什么 JDK 设计者认为这是正确的设计模式,但它确实使处理终止进程变得更加复杂。

值得注意的是,InputStreams Process 持有是 ProcessPipeInputStream 的实例,它实际上有一个 drainInputStream() 方法,这正是我们想要的 - 它读取支持文件描述符中的任何剩余字节并将它们存储在我们的字节缓冲区中。此方法是“进程退出时由进程收割线程调用”,但不幸的是当进程被TERM'ed by .destroy() 时不会调用。

那么,您可以期望的最好的结果就是对您自己的drainInputStream() 行为进行陪审团,并在调用.destroy() 之前调用stdoutstderr。在您排空它们之后但在 .destroy() 完成之前,仍有可能将一些数据写入任一流,但这将获得大部分数据。

【讨论】:

  • 我同意。可怕的决定。他们应该让输入流传递流的结尾,而输出流传递“断管”,就像套接字一样,
【解决方案2】:

除了调用Process.exec()/waitFor()/destroy() 的线程之外,您应该有一个或两个单独的线程读取stdoutstderr(如果将它们合并则一个)。读取线程将获取生成到 EOF 的任何数据。如果你打电话给Process.destroy(),EOF 可能会更快发生,仅此而已。

【讨论】:

  • 是的,但是如果我只是终止进程并然后尝试收集 stderr/stdout 会发生什么?这是我的问题。
  • 你会以错误的顺序做事,就是这样。不要。
  • 在多线程、多核的环境中,什么是“顺序”?因此我的问题。
  • 这是您的订单。您说您正在“杀死[ing] 进程并然后 尝试收集标准输入/标准输出”。 那是命令,而且是错误的命令。做我上面说的。关于 Process.exec() 的陷阱,有一篇很好的 Javaworld 文章。没有提到手,抱歉。
【解决方案3】:

对于任何未来的时间旅行者-Process.destroy() 确实像@dimo414 的回答指出的那样关闭了流。然而,进程的实际终止由Process.toHandle() 检索到的ProcessHandle 处理,这是Process.destroy() 在继续并关闭流之前所做的事情。

长话短说,可以在不关闭流的情况下终止Process

process.toHandle().destroy()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-27
    • 2017-04-23
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    相关资源
    最近更新 更多