ProcessBuilder не останавливается - PullRequest
2 голосов
/ 27 сентября 2011

Я пытаюсь декодировать mp3-файл в wav-файл, используя класс ProcessBuilder под Linux.По какой-то причине процесс не останавливается, поэтому я должен отменить его вручную.

Может кто-нибудь дать мне подсказку на это.Я думаю, что приведенный код очень легко воспроизвести:

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();
     }
 }
}

Вывод 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.BufferedInputStream.read(BufferedInputStream.java:334)
    - locked <0x00000000eb5b1660> (a java.io.BufferedInputStream)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at Test.main(Test.java:17)

Ответы [ 2 ]

7 голосов
/ 27 сентября 2011

Вам необходимо слить как выходные (через getInputStream()), так и ошибочные (через getErrorStream()) потоки процесса, иначе он может заблокироваться.

Цитирование Документации процесса :

Поскольку некоторые собственные платформы предоставляют ограниченный размер буфера только для стандартных входных и выходных потоков, сбой при немедленной записи входного потока иличтение выходного потока подпроцесса может привести к блокировке подпроцесса и даже к тупику.

(что относится как к ошибкам, так и к выходным потокам)

Возможно, вам придется сливать каждый поток в разные потоки, поскольку каждый может блокироваться, когда у него нет данных.

3 голосов
/ 27 сентября 2011

Возможно, вам будет намного проще использовать Java-оболочку LAME, например LAMEOnJ .Таким образом вы избегаете порождения процессов и можете просто взаимодействовать с lame, как если бы это была библиотека Java.

...