ProcessBuilder does not stop
I am trying to decode an mp3 file to a wav file by using the ProcessBuilder class under Linux. For some reason the process does not stop so that I have to cancel it manually.
Could somebody give me a hint on this. I think that the quoted code is very easy to reproduce:
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
Process lameProcess = new ProcessBuilder("lame", "--decode", "test.mp3", "-").start();
InputStream is = lameProcess.getInputStream();
FileOutputStream fileOutput = new FileOutputStream("test.wav");
DataOutputStream dataOutput = new DataOutputStream(fileOutput);
byte[] buf = new byte[32 * 1024];
int nRead = 0;
int counter = 0;
while((nRead = is.read(buf)) != -1) {
dataOutput.write(buf, 0, buf.length);
}
is.close();
fileOutput.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Output of jstack
"main" prio=10 tid=0x0000000002588800 nid=0x247a runnable [0x00007f17e2761000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:236)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputSt开发者_Python百科ream.read(BufferedInputStream.java:334)
- locked <0x00000000eb5b1660> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at Test.main(Test.java:17)
You need to drain both the output (via getInputStream()
) and error (via getErrorStream()
) streams of the process, otherwise it may block.
Quoting the Process documentation:
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, and even deadlock.
(which applies to both the error and output streams)
You'll probably need to drain each stream in different threads because each may block when it has no data.
It might be a lot easier for you to use a LAME Java wrapper like LAMEOnJ. That way you avoid spawning off processes and you can just interact with lame as if it were a Java library.
精彩评论