The Use of Java Process and Runtime of and the Solution of Command Blocking by Calling cmd

  • 2021-09-11 20:21:26
  • OfStack

Java Process and Runtime () use

When java calls cmd to execute bat files, it sometimes gets stuck. I felt confused at the time, Later, after checking the information, Originally, 1 generally calls the program and gets the output stream of the process. However, when I execute such calls on windows, I am always blocked at while, resulting in ffmpeg program not executing after 1. From the official reference documents, we can see that this is due to the buffer problem. Because java process did not empty the contents written by ffmpeg program to the buffer, ffmpeg program 1 was waiting.

I also found many such problems on the Internet, but all of them are controlled by separate threads. I also tried many methods on the Internet, but 1 didn't play any role.

1 It is thought that the buffer of getInputStream has not been emptied, but the problem is that the content of the buffer has not been emptied, but it is not the buffer of getInputStream, but the buffer of getErrorStream, so the problem is solved.

Therefore, when we encounter java calling an external program and causing thread blocking, we can consider using two threads to empty the two input streams obtained by process at the same time, as follows:


 public String excuteBatFile(String file, boolean isCloseWindow) 
    {
        String cmdCommand = null;
        String res = null;
        if(isCloseWindow) 
        {
            cmdCommand = "cmd.exe /c " + file;
        }else 
        {
            cmdCommand = "cmd.exe /k " + file;
        }
        StringBuilder stringBuilder = new StringBuilder();
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(cmdCommand);
            final InputStream is1 = process.getInputStream();
            new Thread(new Runnable() {
                public void run() {
                    BufferedReader bufferedReader = null;
                    String line = null;
                    try {
                        bufferedReader = new BufferedReader(
                                new InputStreamReader(is1, "GBK"));
                        while((line=bufferedReader.readLine()) != null) 
                        {
                            stringBuilder.append(line+"\n");
                        }
                        is1.close();
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }).start(); //  Start a separate thread to empty p.getInputStream() Buffer of 
            InputStream is2 = process.getErrorStream();
            BufferedReader br2 = new BufferedReader(new InputStreamReader(is2)); 
            StringBuilder buf = new StringBuilder(); //  Save the output result stream 
            String line2 = null;
            while((line2 = br2.readLine()) != null) buf.append(line2); // 
            log.info("----res:----" + stringBuilder + "&" + buf);
            return stringBuilder + "&" + buf;
        } catch (Exception e) {
            e.printStackTrace();
            return e.toString();
        }
    }

In this way, we use one thread to read the output stream of process. getInputStream () and another thread to fetch the output stream of process. getErrorStream (), so that we can ensure that the buffer is emptied in time without worrying about the thread being blocked.

Of course, you can also keep the contents of the process. getInputStream () stream as needed, depending on the processing of the calling program.

java Process performs cmd command stream blocking processing

The code is as follows:


public static void runCmd() {
        Process process = null;
        BufferedReader bufferedReader = null;
        try {
            Logger.getLogger(SystemService.class).info("=============  Start restarting the machine  =============");
            process = Runtime.getRuntime().exec("cmd.exe /c shutdown -r -f -t 0");
            bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(process.getInputStream()), Charset.forName("GB2312")));
            //  Open thread to read error output to avoid blocking 
            new StreamInformatonThread(process.getErrorStream(), "error").start();
            String outStr;
            while ((outStr = bufferedReader.readLine()) != null) {
                Logger.getLogger(SystemService.class).info("readLine -------> : " + outStr);
            }
            Logger.getLogger(SystemService.class).info("=============  Restart machine complete  =============");
        } catch (IOException e) {
            Logger.getLogger(SystemService.class).error("=============  Failed to restart the machine  =============");
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

import java.io.*;
/**
 * @Description: Flow blocking processing 
 * @Author: zhangwenchao
 * @Date: 2019/7/9 11:35
 */
public class StreamInformatonThread extends Thread {
    private InputStream is;
    private String str;
    private Logger logger = Logger.getLogger(StreamInformatonThread.class);
    public StreamInformatonThread(InputStream is, String str) {
        this.is = is;
        this.str = str;
    }
    public void run() {
        BufferedReader out = null;
        try {
            out = new BufferedReader(new InputStreamReader(is, "gbk"));
            String line;
            while ((line = out.readLine()) != null) {
                if (str.equals("error")) {
                    logger.info("ErrorStream --------> :" +line);
                } else {
                    logger.info("outLine ---------> :" + line);
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Related articles: