2

I've come across a strange issue. I've used process builder several times to call an executable from a program but have never encountered this before. For debug purposes I made a method which prints the output of the executable to System.out. Everything worked fine and my program nicely exported all of the test gifs I ran.

When it came time to run this program properly for 1000+ gifs I commented out the printout method to improve performance. Once the whole program had run I come back to find that the exportGif did not work. The program ran with no errors but the calling of the process simply did not export the gifs as expected.

After isolating lines in the printout method it seems that the deciding bit of code is the reader.readLine(). Why would this be the case? The executable should have already run, the debug method should only read the output stream after the fact, correct? I'd rather not loop through it's output stream every time as it causes the program to slow considerably.

 private void printProcessOutput(Process process){ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder builder = new StringBuilder(); String line = null; try{ while ( (line = reader.readLine()) != null) { builder.append(line); builder.append(System.getProperty("line.separator")); } }catch(IOException e){ e.printStackTrace(); } System.out.println(builder.toString()); } private void exportGIF(String dirPath) throws IOException { List<String> lines = Arrays.asList("/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/timMaster_4.1.png \"{200.0,467.0}\""); Path headImageFile = Paths.get(System.getProperty("user.dir") + File.separator + "headImageInfo.txt"); Files.write(headImageFile, lines, Charset.forName("UTF-8")); String templatePath = dirPath + File.separator + "template.mp4"; String outputPath = dirPath + File.separator; String headImagePath = headImageFile.toString(); String gifExportExecPath = "/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/GIFExport"; Process process = new ProcessBuilder(gifExportExecPath, "-s", templatePath, "-o", outputPath, "-h", headImagePath).start(); printProcessOutput(process); Files.delete(headImageFile); } 

EDIT

One thing I should add. I noticed that when I comment out the debug method it clocks through all 1000+ iterations in less than ten minutes, But, of course the gifs do not export (the executable doesn't run...? Not sure).

When I include the printout method it is a lot slower. I tried running it overnight but it got stuck after 183 iterations. I've tried profiling to see if it was causing some thrashing but the GC seems to run fine.

1

1 Answer 1

2

You need to consume the output of the Process or it may hang. So you can't comment out printProcessOutput(process);. Instead, comment out the lines that actually do the printing:

try{ while ( (line = reader.readLine()) != null) { //builder.append(line); //builder.append(System.getProperty("line.separator")); } } catch(IOException e){ e.printStackTrace(); } //System.out.println(builder.toString()); 

I generally use this method, which also redirects the error stream:

public static void runProcess(ProcessBuilder pb) throws IOException { pb.redirectErrorStream(true); Process p = pb.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = reader.readLine()) != null) { //System.out.println(line); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

From the Javadoc for Process: "By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, [...] 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." So yes, the process is actually waiting to complete and you can get memory leaks not consuming the err/out streams.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.