Java 中 Process.destroy() 之后 stderr/stdout 流会发生什么?

发布于 2024-08-26 19:11:31 字数 152 浏览 5 评论 0原文

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

I'd like to have a timeout for a process I start from Java. After the timeout, I'd like to kill the process. So far, so good. Problem is, I want to capture stderr/stdout during both normal execution and after a timeout. What happens if I kill the process with destroy()? Can I retrieve the (partial) stderr/stdout produced so far? Or are they gone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲娇萝莉攻 2024-09-02 19:11:31

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

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

值得注意的是,InputStreamProcess 保存的是 ProcessPipeInputStream 实际上有一个 drainInputStream( ) 方法完全符合我们的要求 - 它读取支持文件描述符中的任何剩余字节并将它们存储在我们的字节缓冲区中。该方法“在进程退出时由进程收割者线程调用”,但不幸的是,当进程被 .destroy() 执行 TERM 时,该方法不会被调用。

那么你能期望的最好的结果就是临时操纵你自己的 drainInputStream() 行为,并在调用之前为 stdoutstderr 调用它.destroy()。在耗尽数据之后、.destroy() 完成之前,仍有可能将某些数据写入任一流,但这将获取其中的大部分

Process handling is inherently OS-specific, I'm looking specifically at how Java handles Unix processes here.

It's unfortunate that Process closes its streams when you call .destroy(). I don't know why the JDK designers felt that was the right design pattern, but it certainly makes dealing with terminated processes more complicated.

It's worth noting that the InputStreams Process holds are instances of ProcessPipeInputStream which actually has a drainInputStream() method that does exactly what we'd want - it reads in any remaining bytes in the backing file descriptor and stores them in a byte buffer for us. This method is "called by the process reaper thread when the process exits", but unfortunately is not called when the process is TERM'ed by .destroy().

The best you can hope for then is to jury-rig your own drainInputStream() behavior and call that for both stdout and stderr before you call .destroy(). It's still possible for some data to being written to either stream after you drain them but before .destroy() finishes, but this will get most of it.

樱娆 2024-09-02 19:11:31

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

You should have one or two separate threads reading stdout and stderr (one if you merge them), apart from the thread that calls Process.exec()/waitFor()/destroy(). The reading thread(s) will get any data that is produced up to an EOF. If you call Process.destroy(), the EOF may happen sooner, that's all.

野生奥特曼 2024-09-02 19:11:31

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

因此,长话短说,可以通过执行以下操作来终止进程而不关闭流:

process.toHandle().destroy()

For any future time-travellers - Process.destroy() indeed closes the streams as @dimo414's answer points out. However the actual termination of the process is handled by its ProcessHandle retrieved by Process.toHandle() which is what Process.destroy() does before it then goes ahead and closes the streams.

So to cut a long story short, it is possible to terminate a Process without closing the streams by doing:

process.toHandle().destroy()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文