• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Strange behavior of Runtime.getRuntime().exec(command)

 
Ranch Hand
Posts: 530
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am calling FFmpeg from within Java like this:



I experienced these issues which I don't really understand why:

- If I try to read the process' output from process.getInputStream(), then the program seems to be blocked at the while statement. If I read from the error stream (process.getErrorStream()) then I can read the process' output perfectly. My question is, why don't some program send its output to the input stream but error stream, like the FFmpeg program? How can we know which stream to which the program sends output?

- If I call process.waitFor(), then the program seems to be waiting forever. Why?

Thanks for your insights on these issues.
 
Sheriff
Posts: 28326
96
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Nam Ha Minh wrote:My question is, why don't some program send its output to the input stream but error stream, like the FFmpeg program? How can we know which stream to which the program sends output?



Because the programmers of that program decided to send the output to stderr. But do you need to know why? That's what they did, and you have to deal with it.

You can find out whether output goes to stderr or stdout by experimentally running the program and redirecting one or the other stream and seeing what happens, but again you don't need to know this either. Read on to find out why.

If I call process.waitFor(), then the program seems to be waiting forever. Why?



Because it's waiting for you to consume the output which it sent to stdout or stderr. Those streams don't have an infinitely large buffer, so when the buffer fills and isn't emptied by the receiver (your code), the writer of the stream (the other application) will naturally wait. You should read the classic article When Runtime.exec() won't and implement all of its recommendations.
 
Nam Ha Minh
Ranch Hand
Posts: 530
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Paul for your insight,

The Java doc of waitFor() method does not tell that I have to consume the process' output stream when calling waitFor(). So I thought the waitFor() method will block the program until the process finished without writing any additional code. So is my thought wrong?

Regards.
 
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Nam Ha Minh wrote:Thanks Paul for your insight,

The Java doc of waitFor() method does not tell that I have to consume the process' output stream when calling waitFor(). So I thought the waitFor() method will block the program until the process finished without writing any additional code.



It doesn't say you have to consume it, but it also doesn't say you don't have to. It just says it waits for the process to finish, and that is true; that's what it does. However, if a process is trying to write to a buffer, and that buffer is full, the process can't proceed beyond that point. The process you're executing is probably written something like this:



It has no way of knowing that you are not interested in its output so it's going to patiently sit there at the write line waiting for the buffer to empty. Until that happens, that process is not finished.

So is my thought wrong?



I would think that the behavior you've seen, coupled with the explanation you received, would have answered that question before you asked it.

 
Nam Ha Minh
Ranch Hand
Posts: 530
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Jeff. I got it now.
 
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Note that in terms of the docs, while the docs for waitFor() didn't explain your problem, the docs for the Process class did. You need to look at more than just the individual method doc. The overall class documentation is also important.

Also, the classic article "When Runtime.exec() won't" is an excellent resource, but also rather old at this point. It was written before the ProcessBuilder class was introduced. This is now the recommended replacement for Runtime.exec(). It offers a few improvements. Most of the issues discussed in the original article are still entirely relevant, however - so time spent reading that article is not wasted. But it may be worth your while to replace Runtime.exec() with ProcessBuilder.
 
Nam Ha Minh
Ranch Hand
Posts: 530
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Mike for your insight also
 
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote: You should read the classic article When Runtime.exec() won't and implement all of its recommendations.


Hohoho, those little buggers naming the param to exec() "command" and then MS making "dir" not a command (not an executable.) Talk about Devil in the Details. That was a great article.
 
Bartender
Posts: 3323
86
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes it is a great article. It saved my skin many a year ago and I've also been recommending it ever since.

Not that this will effect the operation of the code but I believe the current recommended way to create a Process is to use ProcessBuilder rather than Runtime.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Um, yes. Good idea.
 
Bartender
Posts: 1166
17
Netbeans IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tony Docherty wrote:Yes it is a great article. It saved my skin many a year ago and I've also been recommending it ever since.

Not that this will effect the operation of the code but I believe the current recommended way to create a Process is to use ProcessBuilder rather than Runtime.



When ProcessBuilder was introduced in 1.5 Runtime.exec() was re-written to use ProcessBuilder behind the scenes. Since ProcessBuilder provides a richer API, unless one needs compatibility with 1.4 or earlier, it makes sense to use ProcessBuilder rather than Runtime.exec().
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Also, one could use ProcessBuilder rather than Runtime.exec(). Just a thought.

 
Richard Tookey
Bartender
Posts: 1166
17
Netbeans IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Also, one could use ProcessBuilder rather than Runtime.exec(). Just a thought.



Sorry Mike - went straight over my head I'm afraid. What am I missing?
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was feeling like we're in a loop. I recommended using ProcessBuilder here a week ago, above.
 
Richard Tookey
Bartender
Posts: 1166
17
Netbeans IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:I was feeling like we're in a loop. I recommended using ProcessBuilder here a week ago, above.



And I was pointing out that using Runtime.exec() is to actually use ProcessBuilder (though with a more restrictive API).
 
"I know this defies the law of gravity... but I never studied law." -B. Bunny Defiant tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic