TShopping

 找回密碼
 註冊
搜索
查看: 1311|回復: 0
打印 上一主題 下一主題

[教學] 使用的Runtime.exec()的一些陷阱

[複製鏈接]
跳轉到指定樓層
1#
發表於 2017-6-29 01:27:09 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
 
Push to Facebook
運行時封裝著java程序的運行時環境。通過Runtime實例,java應用能夠與其運行的環境連接.Runtime在jvm中保持一個單例,所有不能通過運行時類的構造函數。只能通過Runtime.getRuntime()來獲的當前運行時的一個實例。獲得運行時實例後,就可以通過運行時的執行exec()方法在當前JVM進程外啟動其他進程了。很常見的一個應用就是,啟動瀏覽器進程來顯示一個程序的幫助頁面。

在運行時類中存在四個EXEC()重載方法。
的Java代碼
  1. public Process exec(String command);  
  2. public Process exec(String [] cmdArray);  
  3. public Process exec(String command, String [] envp);  
  4. public Process exec(String [] cmdArray, String [] envp);  
複製代碼


主要參數是要啟動進程的名稱,以及啟動該進程時需要的參數。然後是一些環境相關的屬性.envp是已名=值,
形式傳入的。具體查看下源碼便一目了然了。

    通常,啟動另外一個進程後,需要獲取另一個進程的執行結果,然後根據結果執行後續的流程。要獲取外部進程的運行結果,可以調用Process的exitValue()方法。下面代碼中啟動一個java編譯器進程。
的Java代碼
  1. try {  
  2.     Runtime rt = Runtime.getRuntime();  
  3.     Process proc = rt.exec("javac");  
  4.     int exitVal = proc.exitValue();  
  5.     System.out.println("Process exitValue: " + exitVal);  
  6. } catch (Throwable t) {  
  7.     t.printStackTrace();  
  8. }  
複製代碼


不幸的是,你將看到下面的結果:
java.lang.IllegalThreadStateException: process has not exited
at java.lang.ProcessImpl.exitValue(Native Method)
at com.test.runtime.Test.BadExecJavac(Test.java:13)
at com.test.runtime.Test.main(Test.java:5)

原因是exitValue()方法並不會等待外部進程結束。如果外部進程還未結束,exitValue()將會拋出IllegalThreadStateException。解決辦法就是調用過程的WAITFOR()方法.waitfor()方法會掛起當前線程,一直等到外部進程結束。當然使用exitValue()或者WAITFOR()完全取決你的需求。可以設個布爾標誌,來確定使用哪個。運行下面的代碼:
的Java代碼
  1. try {  
  2.     Runtime rt = Runtime.getRuntime();  
  3.     Process proc = rt.exec("javac");  
  4.     int exitVal = proc.waitFor();  
  5.     System.out.println("Process exitValue: " + exitVal);  
  6. } catch (Throwable t) {  
  7.     t.printStackTrace();  
  8. }  
複製代碼


發現程序被阻塞了,什麼原因呢?JDK的Javadoc文檔解釋說:
由於一些本地平台只為標準輸入和輸出流提供有限的緩衝區大小,因此無法及時寫入輸入流或讀取子進程的輸出流可能會導致子程序阻塞,甚至死鎖。
翻譯:
一些平台只為標準輸入提供有限的緩存。錯誤的寫子進程的輸入流或者錯誤的都子進程的輸出流都有可能造成子進程的阻塞,甚至是死鎖。

解決上面問題的辦法就是程序中將子進程的輸出流和錯誤流都輸出到標準輸出中。
的Java代碼
  1. try {  
  2.     Runtime rt = Runtime.getRuntime();  
  3.     Process proc = rt.exec("javac");  
  4.     InputStream stderr = proc.getErrorStream();  
  5.     InputStreamReader isr = new InputStreamReader(stderr);  
  6.     BufferedReader br = new BufferedReader(isr);  
  7.     String line = null;  
  8.     System.out.println("<ERROR>");  
  9.     while ((line = br.readLine()) != null)  
  10.         System.out.println(line);  
  11.     System.out.println("</ERROR>");  
  12.     int exitVal = proc.waitFor();  
  13.     System.out.println("Process exitValue: " + exitVal);  
  14. } catch (Throwable t) {  
  15.     t.printStackTrace();  
  16. }  
複製代碼


上面的代碼中僅僅是輸出了錯誤流,並沒有輸出子進程的輸出流。在程序中最好是能將子進程的錯誤流和輸出流都能輸出並清空。


 

臉書網友討論
*滑块验证:
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2024-4-23 21:44 , Processed in 0.099870 second(s), 22 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表