情景再现
test.py
#!/usr/bin/python
import time
import sys
print "Start : %s" % time.ctime()
time.sleep( 5 )
print "End : %s" % time.ctime()
for i in range(0, 1000000):
sys.stderr.write("msg")
Test.java
import java.io.IOException;
/**
* @author zhy
* @date 2020/2/12 15:17
*/
public class Test {
public static void main(String[] args) throws IOException {
Process process = null;
try {
process = Runtime.getRuntime().exec("python test.py");
process.waitFor();
int i = process.exitValue();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.先直接执行test.py
python test.py
可以看到程序正常结束了,错误信息也正常打印了
2.执行java代码,Test.java
//编译
javac Test.java
//执行
java Test
发现根本无法获取py文件执行成功返回的0
发现问题
Runtime.getRuntime()返回当前应用程序的Runtime对象,该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信息。
它的所有标准io(即stdin,stdout,stderr)操作都将通过三个流(getOutputStream(),getInputStream(),getErrorStream())重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败,则可能导致子进程阻塞,甚至产生死锁。(如果程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waifor()
process .getErrorStream():获得子进程的错误输出流
process .getInputStream():获得子进程的普通输出流
解决
修改java中的代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author zhy
* @date 2020/2/12 15:17
*/
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec("python test.py");
final InputStream is1 = p.getInputStream();
new Thread(() -> {
BufferedReader br = new BufferedReader(new InputStreamReader(is1));
try{
while(br.readLine() != null) ;
}
catch(Exception e) {
e.printStackTrace();
}
}).start();
InputStream is2 = p.getErrorStream();
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
while(br2.readLine() != null){}
int i = p.waitFor();
System.out.println(i);
}
}