繁体   English   中英

如果父进程没有在Java中使用stdout / stderr,为什么进程会挂起?

[英]Why does process hang if the parent does not consume stdout/stderr in Java?

我知道如果你在Java中使用ProcessBuilder.start来启动一个外部进程,你必须使用它的stdout / stderr(例如,见这里 )。 否则外部进程会在启动时挂起。

我的问题是为什么它以这种方式工作。 我的猜测是JVM将执行过程的stdout / stderr重定向到管道,如果管道没有空间,则对管道的写入阻塞。 是否有意义?

现在我想知道为什么 Java会这样做。 这个设计背后的理由是什么?

Java在这方面没有做任何事情。 它只是使用OS服务来创建管道。

在这方面,所有类似操作系统和Windows的Unix都表现相同:在父级和子级之间创建了一个带有4K的管道。 当该管道已满(因为一侧未读取)时,写入过程会阻塞。

这是自管道诞生以来的标准。 没有多少Java可以做到。

你可以争辩说Java中的进程API是笨拙的并且没有很好的默认值,比如简单地将子流连接到与父进程相同的stdin / stdout,除非开发人员用特定的东西覆盖它们。

我认为目前的API有两个原因。 首先,Java开发人员(即Sun / Oracle的人员)确切知道流程API的工作原理以及您需要做什么。 他们非常了解他们并没有发现API可能令人困惑。

第二个原因是没有良好的违约对大多数人有效。 你无法真正连接父母和孩子的标准差; 如果你在控制台上键入内容,输入应该进入哪个进程?

同样,如果你连接stdout,输出将在某处。 如果您有一个Web应用程序,可能没有控制台或输出可能会在没有人期望的地方。

管道已满时甚至无法抛出异常,因为在正常操作期间也可能发生异常。

它在过程javadoc中解释:

默认情况下,创建的子进程没有自己的终端或控制台。 它的所有标准I / O(即stdin,stdout,stderr)操作将被重定向到父进程,在那里可以通过使用方法getOutputStream(),getInputStream()和getErrorStream()获得的流来访问它们。 父进程使用这些流向子进程提供输入并从子进程获取输出。 由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞甚至死锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM