[JAVA] Process exec 실행시 Stream 처리 주의 (hang 이슈)

Woong·2022년 5월 16일
0

Java

목록 보기
9/21

Process 를 이용한 하위프로세스 실행

  • Java 에서 Process exec 실행시, stream 처리 미흡시 hang이 발생할 수 있다.
try {
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec(command);
    process.waitFor();
} catch (Exception e) {
    ....
}
  • 위 예제에서는 프로세스 실행시 스트림 처리가 누락됨
    • 하위 프로세스의 스트림 버퍼 문제로 인해 hang 발생할 가능성이 있다.
    • java.lang.Process 클래스의 API 문서에도 다음과 같이 이를 명시하고 있다.
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

몇몇 네이티브 플랫폼이 표준 입출력 스트림에 제한된 버퍼 크기만 허용하기 때문에, 입력 스트림을 쓰거나 출력 스트림을 읽을 때 일시적인 실패가 일어나면 하위 프로세스가 차단되거나 교착 상태에 빠질 수도 있다.

해결방안

1. Apache Commons 라이브러리 활용

  • 기본으로 System.out과 System.err로 실행 결과를 출력한다.
    • 별도로 System.out으로 스트림을 복사하는 printStream() 메서드를 호출할 필요가 없다.
    • 단, 그대로 사용할 경우 표준 출력으로 인한 성능 저하 이슈가 있을 수 있다.
public void byCommonsExec(String[] command)  
        throws IOException,InterruptedException {
    DefaultExecutor executor = new DefaultExecutor();
    CommandLine cmdLine = CommandLine.parse(command[0]);
    for (int i=1, n=command.length ; i<n ; i++ ) {
        cmdLine.addArgument(command[i]);
    }
    executor.execute(cmdLine);
}

2. Null stream 으로 Redirect

  • redirectOutput, redirectError 는 스트림을 부모프로세스 등으로 연결하는 메소드
  • output, err 스트림을 Redirect.INHERIT 로 지정
    • NullInputStream 으로 넘겨 출력이 전달되지 않도록 함
public void byProcessBuilderRedirect(String[] command) throws IOException, InterruptedException {
    ProcessBuilder builder = new ProcessBuilder(command);
    builder.redirectOutput(Redirect.INHERIT);
    builder.redirectError(Redirect.INHERIT);
    builder.start();
}

references

0개의 댓글