关于JAVA输入输出流造成的Runtime线程阻塞问题【新人笔记】

萌新最近搬砖遇到一个问题,上面让我做一个dump文件的自动解析系统,至于解析的工具,准备用的是google的breakpad,项目部署环境是linux+jdk1.8。其他的无关紧要也就不谈了。

一开始写了一个demo放到测试机上面跑,最初代码如下(只保留转换相关的代码,所以不可以运行):

import java.io.InputStreamReader;

public class DumpAnalyseUtil {

    public static boolean analyseDumpFile(String stackPath, String dumpPath, String symPath, String logPath){
        boolean result = false;
        Process process = null;

        File stackFile = new File(stackPath);
        File dumpFile = new File(dumpPath);
        File symbolFile = new File(symPath);
        File logFile = new File(logPath);

        try{
            if (stackFile.exists() && dumpFile.exists() && symbolFile.exists()){
                String command = stackPath + " " + dumpPath + " " + symPath + " > " + logPath;
                System.out.println(command);
                Runtime.getRuntime().exec(command).waitFor();
                result = true;
            }
        }catch (Exception e){
            System.out.println("Dump File Analysis Error: " + e.getMessage());
            if (process != null){
                try{
                    process.getErrorStream().close();
                    process.getInputStream().close();
                    process.getOutputStream().close();
                }catch (IOException ie){
                    ie.printStackTrace();
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        String stackPath = "/data/breakpad/src/processor/minidump_stackwalk";
        String dumpPath = "/data/dump/lalala.dmp";
        String symPath = "/data/symbols/";
        String logPath = "/data/symbols/123456.log";
        boolean result = analyseDumpFile(stackPath, dumpPath, symPath, logPath);
        System.out.println(result);
    }
}

在测试环境中运行这个demo的时候,程序跑到waitFor()方法那里就卡住不动了。。。

后来发现是自己的java基础还是有些薄弱,java在执行runtime命令时,输入流和错误流都会不断地进入JVM的缓冲区(一般来说不会有输出流,但是如果我们的命令和java程序有信息交互的话,比如需要我们通过程序输入什么参数的时候,这时候也会产生一些输出流进入缓冲区,但是这些输出流应该很快就被读取了,所以出现阻塞一般都是输入流和错误流引起的)。如果我们不去将缓冲区的这些信息流读出来的话,他们就会一直待在缓冲区,并最终将其填满,造成runtime的阻塞。

知道了问题的所在,就好解决了。既然这些数据流不读取就会淤积的话,读出来就好了,于是有了改进第一版(只放了改进的那部分代码):

Process exec = Runtime.getRuntime().exec(command);

BufferedReader insertReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(exec.getErrorStream()));

exec.waitFor();

还有一种方式,就是如果这个错误输出流里面的信息对你来说没有什么价值的话,可以利用ProcessBuilder的redirectErrorStream方法,来把错误流和输入流整合到一起,一并读出来:

ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
Process p = processBuilder.start();
InputStream is = p.getInputStream();
BufferedReader bs = new BufferedReader(new InputStreamReader(is));

另外,如果你的输入流信息非常多,比如拷贝文件的话,则可以单独起一个线程来读取输入流中的信息:

(这一块是参考了 望星辰大海 的博客中的代码 点击打开链接

就不具体放出来了,有兴趣可以点击链接过去看一下。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页