来自 javadocjava.lang.Process http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Process.html:
创建进程的方法可能不适用于某些本机平台上的特殊进程,例如本机窗口进程、守护进程、Microsoft Windows 上的 Win16/DOS 进程或 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout、stderr)操作都将通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从子进程获取输出。由于某些本机平台只为标准输入输出流提供有限的缓冲区大小,因此未能及时写入子进程的输入流或读取子进程的输出流可能会导致子进程阻塞,甚至死锁。
我知道这个问题,当然,如果您想与子流程进行通信,那么及时与子流程进行通信是有意义的。
但是,如果您只想启动一个进程而不关心 I/O,该怎么办?在Java中,有没有办法释放父进程中专门用于管理子进程的资源? (例如I/O管道和等待子进程退出状态)
如果我在父进程中执行以下命令:
Process.getOutputStream().close();
Process.getInputStream().close();
Process.getErrorStream().close();
我还需要担心死锁吗? (例如,如果子进程连续向其自己的标准输出发送数据)
您在这里有两件事需要担心:
- 当您无法使用它时,进程会阻塞并尝试写入标准输出吗?
- 该流程将如何解释正在关闭的流?
关闭输出流显然不会导致死锁,除非进程需要输入。然而,该过程will检测到已到达流末尾,并可能相应地终止。拿grep
例如。当您关闭其输入流时,该程序将终止。
忽略输入的最简单、最安全的方法是创建一个在单独线程上消耗和丢弃输入的库。你可能已经看过这个课程StreamGobbler
漂浮在周围就是这样做的。
Edit
所以我用两个不同的子进程程序尝试了以下操作:
Process proc = new ProcessBuilder(appStr).start();
proc.getInputStream().close();
InputStream eos = proc.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(eos));
for ( String line = null; (line = reader.readLine()) != null; ) {
System.err.println(line);
}
System.out.println(proc.waitFor());
第一次,我调用了一个简单的 Java 应用程序:
public class App {
public static void main(String[] args) throws Exception {
for ( int i = 0; i < 1000; i++ ) {
System.out.println(i);
}
}
}
进程正常结束,父进程终止并显示0
退出代码。
但后来我尝试针对本机程序调用它,在本例中是cat
变化,回显文件。在这种情况下,子进程失败,并向错误流写入一条乱码消息,抱怨标准输出流已关闭。它以非零退出代码异常终止。
因此,实际上您建议的关闭流的方法在一般情况下不会成功。您必须知道子进程可以优雅地处理丢失其输出流的情况,但我怀疑大多数应用程序不会。我的直觉是,当输出流关闭时,Java 可以做一些优雅的失败,这样从程序的角度来看,流仍然打开,没有人在监听。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)