2015-04-28 91 views
0

我有一個應用程序在我的PC的指定位置調用java測試類。現在路徑是硬編碼的,我通過從命令行執行它來檢查它的工作情況(如果你想看到它:java -cp C:\Users\user\Documents\workspace\test\build\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest),所以我知道該命令工作正常。確定是否從另一個java應用程序執行java執行成功

事情是,當我做Runtime.getRuntime().exec(command),如果我嘗試記錄其生成的過程的結果InputStream和ErrorStream,程序就會陷入困境。我試着用exitValue()和waitFor(),但第一次拋出一個不完整的錯誤,第二次也卡住了。奇怪的是,如果我沒有碰到這些(流,或使用函數)的任何東西,程序沒有問題的結局。

所以我的問題是:這是爲什麼呢?下一步是使用給定的參數構建命令,但是如果我看不到結果輸入,我不能完全確定測試是否正在運行。

的代碼,如果你想看到它:

Runtime runtime=Runtime.getRuntime(); 
logger.debug("Attempting to execute the test {} at path {}",classpath,applicationLocation); 

String command="java -cp C:\\Users\\user\\Documents\\workspace\\test\\build\\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest"; 
Process process=runtime.exec(command); 
BufferedReader stdInput = new BufferedReader(new 
     InputStreamReader(process.getInputStream())); 

BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(process.getErrorStream())); 

System.out.println("Here is the standard output of the command:\n"); 
String s = null; 
while ((s = stdInput.readLine()) != null) { 
    System.out.println(s); 
} 

System.out.println("Here is the standard error of the command (if any):\n"); 
while ((s = stdError.readLine()) != null) { 
    System.out.println(s); 
}  
+0

正如一個測試:你能嘗試閱讀無論是在時間和交替流一行他們之間只要進程還活着? – Dawnkeeper

+0

使用本地套接字互相連接並進行通信。 – farukdgn

+0

@Dawnkeeper:我試了一下,它打印出整個東西,並退出罰款。現在我只需要處理輸出。非常感謝! – KatVolkov

回答

0

請務必關閉2流:

String command="java -cp C:\\Users\\user\\Documents\\workspace\\test\\build\\test.jar org.junit.runner.JUnitCore us.test.DynamicWebserviceInvocationTest"; 
    Process process=runtime.exec(command); 
    BufferedReader stdInput = new BufferedReader(new 
      InputStreamReader(process.getInputStream())); 

    BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(process.getErrorStream())); 

    // read the output from the command 
    System.out.println("Here is the standard output of the command:\n"); 
    String s = null; 
    while ((s = stdInput.readLine()) != null) { 
     System.out.println(s); 
    } 
    stdInput.close(); 

    // read any errors from the attempted command 
    System.out.println("Here is the standard error of the command (if any):\n"); 
    while ((s = stdError.readLine()) != null) { 
     System.out.println(s); 
    } 
    stdError.close(); 
+0

在單線程中這樣做並不安全。這取決於孩子輸出的數據量以及操作系統使用的緩衝區數量。在你的情況下,如果進程想要寫8k錯誤消息,然後輸出1行正常輸出,8k將填充錯誤緩衝區並且根本不寫任何標準輸出,你的第一個循環將阻塞並且不會消耗stderr。 – eckes

1

你絕對必須閱讀在單獨的線程兩個流。 (閱讀Process課程的Javadoc)。如果您等待結束,或先讀取一個流,然後再讀取其中一個流,則可能會發生命令的輸出緩衝區已滿並且會阻塞(取決於您先讀取的內容,它會在stdout或stderr上)。通常在當前線程中使用waitFor(),並讓後臺線程排空輸出(這也允許在沒有輪詢的情況下檢測子進程的結束)。

如果您只想使用一個(額外)線程,則可以將stderr重定向到stdout。如果您想避免讀取流,可以設置 ProcessBuilder功能inheritIO()。這允許將流寫入現有輸出,因此您不需要一個線程來獨立讀取。

有BTW各種libararies提供exec工具(例如Apache Commons Exec has some streams),它們爲Process提供活動流排水,日誌記錄或泵送。

此外,它也可能是一個好主意,先關閉標準輸入,如果輸入的命令等待:p.getOutputStream().close();