2010-09-14 21 views
5

我有一些關於ProcessBuilder的問題。該程序基本上是一個調用命令行腳本的簡單包裝器。java:ProcessBuilder使內存生豬

當通過終端自行運行腳本時,內存消耗保持在2G以下。 當通過java包裝器運行腳本時,內存消耗劇增,甚至8G很快填滿,導致內存不足錯誤。

啓動該過程的代碼只是:

public static int execute(String command) throws IOException 
{ 
    System.out.println("Executing: " + command); 

    ProcessBuilder pb = new ProcessBuilder(command.split(" +")); 
    Process p = pb.start(); 

    // display any output in stderr or stdout 
    StreamConsumer stderr = new StreamConsumer(p.getErrorStream(), "stderr"); 
    StreamConsumer stdout = new StreamConsumer(p.getInputStream(), "stdout"); 
    new Thread(stderr).start(); 
    new Thread(stdout).start(); 

    try { 
    return p.waitFor(); 
    } catch (InterruptedException e) { 
    throw new RuntimeException(e); 
    } 
} 

的StreamConsumer類只是消耗標準輸出/ stderr流並在控制檯上顯示它們的類。

...問題是:爲什麼地球上的內存消耗會爆炸?

問候,
阿爾諾

編輯:

  • 無論我使用的ProcessBuilder或 Runtime.getRuntime.exec(...),該 結果是一樣的。
  • 爆發往往出現內存由 shell腳本調用UNIX '排序' 期間調用:

    好吧,這裏:吉姆駐軍的請求

sort big-text-file > big-text-file.sorted 

編輯2是我省略的StreamConsumer類,因爲它比較簡單:

class StreamConsumer implements Runnable 
{ 
    InputStream stream; 
    String descr; 

    StreamConsumer(InputStream stream, String descr) { 
     this.stream = stream; 
     this.descr = descr; 
    } 

    @Override 
    public void run() 
    { 
     String line; 

     BufferedReader brCleanUp = 
      new BufferedReader (new InputStreamReader (stream)); 

     try { 
      while ((line = brCleanUp.readLine()) != null) 
       System.out.println ("[" + descr + "] " + line); 
      brCleanUp.close(); 
     } catch (IOException e) { 
      // TODO: handle exception 
     } 
    } 
} 
+0

只是一個猜測:如果StreamConsumer實際上沒有使用子進程的文本,那麼文本可能會保存在一個不斷增大的緩衝區中。 – 2010-09-14 12:01:43

+0

所有stdout&stderr已成功顯示在控制檯中 – dagnelies 2010-09-14 12:03:10

+2

如何測量內存消耗? _進程正在消耗內存...... JVM?貝殼?排序過程?在沒有看到StreamConsumer的情況下,很難知道那裏是否存在錯誤。你確定內存消耗對於進程是私有的還是僅僅是暫時的I/O緩衝區?你真的沒有提供太多的東西繼續下去。 – 2010-09-14 16:37:01

回答

2

如果你改變你的命令是這樣的: sort -o big-text-file.sorted大文本文件

它總是一樣嗎?

+0

好點 - 也許是重定向錯誤。對此有何反應? – 2011-10-15 17:31:35

0

也許是因爲這些StreamConsumer線程不是守護進程,所以當你的進程返回時它們不會死亡並且垃圾收集?您可以嘗試:

//... 
final StreamConsumer stderr = new StreamConsumer(p.getErrorStream(), "stderr"); 
final StreamConsumer stdout = new StreamConsumer(p.getInputStream(), "stdout"); 
final Thread stderrThread = new Thread(stderr); 
final Thread stdoutThread = new Thread(stdout); 
stderrThread.setDaemon(true); 
stdoutThread.setDaemon(true); 
stderrThread.start(); 
stdoutThread.start(); 
//... 

這種行爲是發生在單個調用還是多次執行後?