3

LinuxでProcessBuilderクラスを使用して、mp3ファイルをwavファイルにデコードしようとしています。なんらかの理由でプロセスが停止しないため、手動でキャンセルする必要があります。

誰かが私にこれについてのヒントを教えてもらえますか?引用されたコードは非常に簡単に再現できると思います。

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)
4

2 に答える 2

9

getInputStream()プロセスの出力(via)ストリームとエラー(via )ストリームの両方をドレインする必要がありgetErrorStream()ます。そうしないと、ブロックされる可能性があります。

プロセスドキュメントの引用:

一部のネイティブプラットフォームでは、標準の入力ストリームと出力ストリームに限られたバッファサイズしか提供されないため、サブプロセスの入力ストリームの書き込みまたは出力ストリームの読み取りに失敗すると、サブプロセスがブロックされ、デッドロックが発生する可能性があります。

(これはエラーストリームと出力ストリームの両方に適用されます)

データがない場合は各ストリームがブロックされる可能性があるため、おそらく各ストリームを異なるスレッドでドレインする必要があります。

于 2011-09-26T22:55:46.580 に答える
3

LAMEOnJのようなLAMEJavaラッパーを使用する方がはるかに簡単な場合があります。そうすれば、プロセスの生成を回避し、Javaライブラリであるかのようにlameを操作できます。

于 2011-09-26T23:03:57.573 に答える