2013-05-30 50 views
2

我正在開發一個包含3個按鈕的Java桌面應用程序(我們稱之爲控制檯):其中兩個啓動Win32應用程序;第三應該啓動一個可執行的JAR:用ProcessBuilder啓動的Java應用程序在一段時間後被阻塞

ProcessBuilder pb = new ProcessBuilder("java", "-jar", testDrivePath); 
Process process = pb.start(); 

其中testDrivePath是對罐子的路徑(類似於 「C:\程序\ TestDrive.jar」)

的TestDrive.jar應用程序正確啓動,但過了一段時間就會阻塞,無法進行任何操作。

如果關閉控制檯,TestDrive.jar會重新啓動!

如果我將TestDrive.jar作爲一個獨立版本啓動(沒有從控制檯調用它),那麼一切都是正確的。

任何人都可以建議嗎?

+4

從[工藝的Javadoc](http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html):「*未能及時寫輸入流或讀子流程的輸出流可能導致子流程阻塞,甚至導致死鎖。*「。這可能是你的問題嗎? – assylias

回答

2

您可能需要從流程中讀取輸出流。你可以像這樣得到stdout和stderr流:

InputStream stdout = process.getInputStream(); 
InputStream stderr = process.getErrorStream(); 

您可以創建工作線程以異步讀取這些流。

Thread threadOut = new Thread(new MyInputStreamSink(stdout, "out")); 
Thread threadErr = new Thread(new MyInputStreamSink(stderr, "err")); 

threadOut.setDaemon(true); 
threadErr.setDaemon(true); 
threadOut.setName(String.format("stdout reader")); 
threadErr.setName(String.format("stderr reader")); 

threadOut.start(); 
threadErr.start(); 

下面是一個Runnable的實現,它使用流的輸出。

private static class MyInputStreamSink implements Runnable { 
    private InputStream m_in; 
    private String m_streamName; 

    MyInputStreamSink(InputStream in, String streamName) { 
     m_in = in; 
     m_streamName = streamName; 
    } 

    @Override 
    public void run() { 
     BufferedReader reader = null; 
     Writer writer = null; 

     try { 
      reader = new BufferedReader(new InputStreamReader(m_in)); 

      for (String line = null; ((line = reader.readLine()) != null);) { 
       // TODO: Do something with the output, maybe. 
      } 
     } catch (IOException e) { 
      s_logger.log(Level.SEVERE, "Unexpected I/O exception reading from process.", e); 
     } 
     finally { 
      try { 
       if (null != reader) reader.close(); 
      } 
      catch (java.io.IOException e) { 
       s_logger.log(Level.SEVERE, "Unexpected I/O exception closing a stream.", e); 
      } 
     } 
    } 
} 
+0

感謝您的建議。實際上,這些應用程序是完全獨立的:不需要參數或數據交換。對於使用Process Builder生成的每個Process,是否強制使用ErrorStream和InputStream? – Enrico

+0

即使輸出與父進程不相關,子進程也可以阻塞,即使沒有任何內容正在讀取其輸出。我發現它最簡單(有時在調試過程中提供信息),以便在父進程中使用子進程的stdout/stderr。如果孩子沒有寫任何東西,或者孩子關閉了STDOUT_FILENO和STDERR_FILENO,還沒有嘗試過會發生什麼。順便說一句,歡迎來到StackOverflow。您可以*點擊左邊的向上三角形* upvote *多個你認爲有用的答案。通過點擊左邊的複選標記,您可以*接受*您認爲最好的答案。 –

+0

感謝Andy提供的有用建議! – Enrico

相關問題