• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            在java中使用Runtime.exec()時要注意的問題

            Posted on 2014-04-08 15:20 鑫龍 閱讀(3461) 評論(0)  編輯 收藏 引用 所屬分類: Java

            程序如下:

            import java.util.*;

            import java.io.*;

            public class BadExecJavac

            {

                public static void main(String args[])

                {

                    try

                    {           

                        Runtime rt = Runtime.getRuntime();

                        Process proc = rt.exec("javac");

                        int exitVal = proc.exitValue();

                        System.out.println("Process exitValue: " + exitVal);

                    } catch (Throwable t)

                      {

                        t.printStackTrace();

                      }

                }

            }

            運行結(jié)果如下

            E:\classes\com\javaworld\jpitfalls\article2>java BadExecJavac
            java.lang.IllegalThreadStateException: process has not exited       
            at java.lang.Win32Process.exitValue(Native Method)       
            at BadExecJavac.main(BadExecJavac.java:13)

            這是因為當進程還沒有結(jié)束的情況下,調(diào)用exitValue方法會拋出IllegalThreadStateException.當然了我們會問為什嗎這個方法不會等到進程結(jié)束在返回一個合理的值?

            在檢查Process類的所有可用方法以后我們發(fā)現(xiàn)WairFor()是一個更合適的方法。事實上waitFor也會返回exit value。這意味著你不可以同時用exitvalue和waitfor,而是只能選擇一個。

            當然了也有情況你要在waitfor之前用exitvalue方法:就是你不想因為外部程序永遠無法完成而一直等待下去。

            因此為了避免這個陷阱,我們要么捕獲IllegalThreadStateException異常,要么等待進程完成。我們相當然的以為可以用waitfor來等待程序的結(jié)束。代碼如下:

            import java.util.*;
            import java.io.*;
            public class BadExecJavac2{   
               public static void main(String args[])    {       
                  try        {                        
                     Runtime rt = Runtime.getRuntime();           
                     Process proc = rt.exec("javac");           
                     int exitVal = proc.waitFor();           
                     System.out.println("Process exitValue: " + exitVal);       
                  } catch (Throwable t)          {           
                     t.printStackTrace();         
                  }   
               }
            }

            這次在linux下面返回的結(jié)果是2,而在windows下面據(jù)說程序會掛起,關(guān)于其原因我們可以在jdk文檔中找到部分解釋:因為一些操作系統(tǒng)為標準的輸入輸出僅僅提供有限的緩沖區(qū),當不能正確的將信息寫進輸入流或者從輸出流中獲取信息時,就會導致子進程的阻塞,甚至死鎖。現(xiàn)在我們就根據(jù)jdk文檔來處理javac進程的輸出,當你不帶任何參數(shù)運行javac時,它會打印出一系列的有用的提示信息。而這些會被傳送到stderr流中。我們可以寫程序在其返回前獲取這些信息。下面的代碼提供了一個平庸的解決方案。

            import java.util.*;import java.io.*;
            public class MediocreExecJavac{   
               public static void main(String args[])    {       
                   try        {                        
                     Runtime rt = Runtime.getRuntime();           
                     Process proc = rt.exec("javac");           
                     InputStream stderr = proc.getErrorStream();           
                     InputStreamReader isr = new InputStreamReader(stderr);           
                     BufferedReader br = new BufferedReader(isr);           
                     String line = null;           
                     System.out.println("<ERROR>");           
                     while ( (line = br.readLine()) != null)               
                        System.out.println(line);           
                     System.out.println("</ERROR>");           
                     int exitVal = proc.waitFor();           
                     System.out.println("Process exitValue: " + exitVal);       
                  } catch (Throwable t)          {           
                      t.printStackTrace();         
                  }   
               }
            }

            這次程序可以正確的輸出了提示信息,但是我們應(yīng)該注意到其返回代碼是2,我們知道任何非0的返回代碼都表示程序不正常。所以我們需要進一步的查找原因。對于win32而言是file not found,很明顯javac期望我們提供編譯的文件。所以對于永遠掛起的問題,如果你運行的程序會有輸出或者要求輸出入時,你需要處理輸出和輸入。我在linux下面運行的結(jié)果是正確的。前面說了在win32下面2代表是文件沒有找到,而在這種情況下表明是dir.exe沒有找到,(因為根本就沒有這個文件,他們都被封裝到common.com (win95)或者cmd.exe中了。

            下面我們列出一個正確的處理Process的輸入輸出流的方法。需要用一個線程類。

            import java.util.*;
            import java.io.*;
            class StreamGobbler extends Thread{   
               InputStream is;   
               String type;        
               StreamGobbler(InputStream is, String type)    {       
                   this.is = is;       
                   this.type = type;   
               }        

               public void run()    {       
                  try        {           
                      InputStreamReader isr = new InputStreamReader(is);           
                      BufferedReader br = new BufferedReader(isr);           
                      String line=null;           
                  while ( (line = br.readLine()) != null)               
                  System.out.println(type + ">" + line);                
                  } catch (IOException ioe)             {               
                   ioe.printStackTrace();               
                  }   
               }
            }

            用于專門的處理輸入輸出。

            public class GoodWindowsExec{   
                public static void main(String args[])    {       
                    if (args.length < 1)        {           
                        System.out.println("USAGE: java GoodWindowsExec <cmd>");           
                        System.exit(1);       
                    }                
                    try        {                        
                        String osName = System.getProperty("os.name" );           
                        String[] cmd = new String[3];           
                        if( osName.equals( "Windows NT" ) )            {               
                            cmd[0] = "cmd.exe" ;               
                            cmd[1] = "/C" ;               
                            cmd[2] = args[0];           
                        }            else if( osName.equals( "Windows 95" ) )            {               
                            cmd[0] = "command.com" ;               
                            cmd[1] = "/C" ;               
                            cmd[2] = args[0];            }                        
                        Runtime rt = Runtime.getRuntime();            
                        System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]);           
                        Process proc = rt.exec(cmd);            // any error message?           
                        StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");  // any output?           
                        StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");                            // kick them off           
                        errorGobbler.start();           
                        outputGobbler.start();                                                // any error???           
                        int exitVal = proc.waitFor();           
                        System.out.println("ExitValue: " + exitVal);                
                    } catch (Throwable t)          {           
                        t.printStackTrace();          
                    }   
                }
            }

            如果運行如下命令上面的代碼會調(diào)用word程序

            >java GoodWindowExec “abc.doc”

            也就是說文件類型如果window能夠識別它就會調(diào)用對應(yīng)的程序處理。

            StreamGlobbler的最重要作用是他會清空所有的傳遞給他的inputstream,這樣不會造成Process阻塞或者死鎖。

            9999国产精品欧美久久久久久| 久久精品一区二区影院| 69国产成人综合久久精品| 女人香蕉久久**毛片精品| 亚洲精品国产自在久久| 久久久久99精品成人片试看| 99热都是精品久久久久久| 久久久久久精品无码人妻| 伊人久久大香线蕉影院95| 久久久精品国产免大香伊 | 国产视频久久| 亚洲国产精品无码成人片久久| 成人亚洲欧美久久久久| 无码人妻久久一区二区三区免费| 国产福利电影一区二区三区久久老子无码午夜伦不 | 亚洲乱码日产精品a级毛片久久| 亚洲狠狠婷婷综合久久久久| 国产精品99久久精品爆乳| 亚洲国产一成人久久精品| 色8激情欧美成人久久综合电| 国产成人精品久久免费动漫| 精品国产99久久久久久麻豆| 久久精品这里只有精99品| 91久久福利国产成人精品| 国内精品人妻无码久久久影院| 国产精品久久久久久影院 | 国内精品久久久久影院优 | 久久天天日天天操综合伊人av| 久久精品无码一区二区无码 | 久久久久久A亚洲欧洲AV冫| 国产产无码乱码精品久久鸭 | 久久久久久伊人高潮影院| 中文精品久久久久人妻| 久久综合五月丁香久久激情| 99久久婷婷国产综合精品草原| 久久成人国产精品二三区| 99久久精品国产高清一区二区| 无码人妻久久久一区二区三区 | 久久久国产亚洲精品| 精品久久人人爽天天玩人人妻| 国产免费福利体检区久久 |