java processbuilder构建子进程

这两天测试使用processbuilder来构建一个子进程,原来使用Runtime.exec()来启动一个进程,如果不读取stderr,那么有可能会导致进程阻塞,这个官方的api也说了,根据不同的操作系统,不恰当的操作会导致阻塞甚至死锁。使用新的api processbuilder就能将stderr重定向到stdout,这样仅仅读取process的输出流就可以,但是测试的时候发现一些问题。下面讨论的都是基于linux平台。

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process

默认情况下,创建的子进程是没有自己的终端或者控制台,子进程的stdin std out stderr会重定向到父进程,通过PIPE来连接。

subprocess I/O can also be redirected using methods of the ProcessBuilder class

可以使用ProcessBuilder来重定向子进程子的stdin stdout stderr。

java 1.7之后新增了一个类 java.lang.ProcessBuilder.Redirect来实现子进程的标准io重定向的问题,子进程的标准io必定是以下三中之一,

Redirect.PIPE 1.7之前的模式,也是默认的模式,在linux下通过PIPE连接父子进程,注意PIPE缓冲的大小有限制

Redirect.INHERIT 继承父进程的

a redirection to read from a file 读取文件

a redirection to write to a file 写入文件,非追加

a redirection to append to a file 追加写入文件

 

ProcessBuilder同样提供了设置子进程环境变量和工作空间的方法,推荐使用ProcessBuilder。

 

在使用PIPE的情况下,由于linux平台PIPE的缓冲大小是64KB,一个PIPE连接着父进程和子进程,如果父进程不去读取子进程的输出,那么如果子进程在执行过程中一直使用stdout进行输出,一旦写满,子进程就会阻塞,一直到父进程去一行一行读取这些输出,也就是说在ProcessBuilder.start之后,父进程和子进程将分别各自运行,但是它们之间有PIPE相连。

通过ulimit -a查看到 pipe size 一次原子写入为:512Bytes*8=4096Bytes

查看缓冲条目个数:cat /usr/src/kernels/3.10.0-327.el7.x86_64/include/linux/pipe_fs_i.h文件 16

PIPE缓冲大小是4096Bytes*16=64KB

在使用FILE来重定向的情况下,父进程的退出与否不会影响子进程的执行。

在linux平台下,默认使用PIPE,发现父进程退出后,子进程也退出了,具体原因可能是PIPE的读取一端关闭,导致写入的一端在写入时收到SIGPIPE信号,这个信号导致子进程退出。

在linux平台下,ProcessBuilder.inheritIO()来使产生的子进程继承父进程的标准io,发现执行时,子进程的输出和父进程一样,都输出到控制台,但是父进程退出之后,子进程会继续执行。

转载于:https://my.oschina.net/wuxiaofei/blog/909286

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值