2011-09-26 1 views
2

Linux에서 ProcessBuilder 클래스를 사용하여 mp3 파일을 wav 파일로 디코딩하려고합니다. 어떤 이유로 프로세스가 중지되지 않아 수동으로 취소해야합니다.ProcessBuilder가 중지되지 않습니다.

누군가 내게이 힌트를 줄 수 있습니까? jstack을의

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

출력을

"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) 
+0

'Process' 객체에서'waitFor()'메서드가 호출되지 않아야합니까? – biziclop

+1

어디서 멈 춥니 까? 'jstack '또는'kill -3 '를 쓰레드 덤프를 얻는다. –

+0

당신이'read()'호출에 매달린 것처럼 보입니다. 외부 프로세스가 종료 되었습니까? –

답변

7

당신은 프로세스의 흐름을 (getInputStream() 통해) 모두 출력 드레인 (getErrorStream()를 통해) 오류해야합니다 나는 인용 코드가 재현하는 것이 매우 쉽다는 것을 생각 그렇지 않으면 차단 될 수 있습니다. Process documentation 인용

: 일부 네이티브 플랫폼에 표준 입력 및 출력 스트림을위한 제한된 버퍼 크기를 제공하기 때문에

를 즉시 입력 스트림을 작성 또는 서브 프로세스의 출력 스트림을 판독 실패로 구성 프로세스의 원인 블록 및 심지어 교착 상태. (오류 출력 스트림을 모두 적용)

당신은 아마 데이터가없는 경우 각 차단할 수 있기 때문에 다른 스레드에서 각 스트림을 배출해야합니다.

+0

또는 [ProcessBuilder.redirectErrorStream()] (http://download.oracle.com/javase/6/docs/api/java/lang/ProcessBuilder.html#redirectErrorStream (boolean))을 사용하여 스트림을 하나로 결합 할 수 있습니다 더 쉽게 삶을 살 수 있습니다. – Jon7

+0

+1. 나의 조언은'java.util.concurrent'를 사용하여 새로운 스레드를 생성하고 관심있는'InputStream'을 누적을위한 새로운 스레드로 전달하는 것입니다. 아파치 IO 커먼즈를 사용하면 한 줄로 처리 할 수 ​​있습니다 :'IOUtils.toString (inputStream, YOUR_CONSOLE_CHARSET);' –

+1

@ Jon7 redirectErrorStream()은이 특별한 경우에는 좋지 않습니다. 출력 스트림은 WAVE 출력으로 사용됩니다. 거기에 섞인 오류 메시지가 WAV 파일을 손상시킵니다. – prunge

3

LAMEOnJ과 같은 LAME Java 래퍼를 사용하는 것이 훨씬 쉽습니다. 그렇게하면 프로세스를 생성하는 것을 피할 수 있으며 마치 Java 라이브러리 인 것처럼 절름발이와 상호 작용할 수 있습니다.