Friday, September 4, 2015

Java ProcessBuilder has 32KB buffer, .waitFor() hangs if it isn't cleared

If you're running a simple Java ProcessBuilder, and it hangs and never returns when you start it and then run .waitFor() without running separate threads to make sure it finishes nicely, it may be because the ProcessBuilder is out of memory in its STDOUT buffer. The buffer is 32KB, so if your process returns more data than that and you're just trying to do a simple, synchronous .waitFor() call and just wait for it to return with all the data, it will never return if it hits this buffer limit. You must either consume the buffer, use threads, or redirect the output somewhere, like a temporary file. Kudos to "kjkoster" on this thread for the idead and code: http://java-monitor.com/forum/showthread.php?t=4067.

It goes something like this:
final File tmp = File.createTempFile("out", null);
try {
    tmp.deleteOnExit();

    final ProcessBuilder processBuilder = new ProcessBuilder();
    processBuilder.command("cat", filename).redirectErrorStream(true).redirectOutput(tmp);
    final Process process = processBuilder.start();
    final int exitCode = process.waitFor();

    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(tmp)));
    String line = "";   
    while ((line = reader.readLine())!= null) {
        System.out.println(line);
    }
    reader.close();
    tmp.delete();
} finally {
    tmp.delete();
}