日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

[转]Java中Runtime.exec的一些事

發布時間:2025/5/22 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转]Java中Runtime.exec的一些事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0 預備知識

1 不正確的調用exitValue

2不正確的調用waitFor

3 一種可接受的調用方式

4 調用認為是可執行程序的時候容易發生的錯誤

5 window執行的良好示例

6 不良好的重定向命令輸出

7 良好的重定向輸出示例

8 總結

9 問答

?

0?預備知識

Runtime類是一個與JVM運行時環境有關的Singleton類,有以下幾個值得注意的地方:

0.1 Runtime.getRuntime()可以取得當前JVM的運行時環境,這也是在Java中唯一得到運行時環境的方法。

0.2 Runtime上其他大部分的方法都是實例方法,也就是說每次進行運行時調用時都要用到getRuntime方法。

0.3 Runtime中的exit方法是退出當前JVM的方法,估計也是唯一的。System類中的exit實際上也是通過調用Runtime.exit()來退出JVM的。

Java對Runtime返回值的一般規則,0代表正常退出,非0代表異常中止,這只是Java的規則,在各個操作系統中總會發生一些小的混淆。

0.4 Runtime.addShutdownHook()方法可以注冊一個hook在JVM執行shutdown的過程中,方法的參數只要是一個初始化過但是沒有執行的Thread實例就可以。(注意,Java中的Thread都是執行過了就不值錢的哦)

0.5說到addShutdownHook這個方法就要說一下JVM運行環境是在什么情況下shutdown或者abort的。

Shutdown:當最后一個非精靈進程退出或者收到了一個用戶中斷信號、用戶登出、系統shutdown、Runtime的exit方法被調用時JVM會啟動shutdown的過程,在這個過程開始后,他會并行啟動所有登記的shutdown hook(注意是并行啟動,這就需要線程安全和防止死鎖)。當shutdown過程啟動后,只有通過調用halt方法才能中止shutdown的過程并退出JVM。

Abort:?abort退出時JVM就是停止運行但并不一定進行shutdown。這只有JVM在遇到SIGKILL信號或者windows中止進程的信號、本地方法發生類似于訪問非法地址一類的內部錯誤時會出現。這種情況下并不能保證shutdown hook是否被執行。

0.6 Runtime.exec()方法的所有重載。這里要注意的是:

public Process exec(String[] cmdarray, String[] envp, File dir);

這個方法中cmdArray是一個執行的命令和參數的字符串數組,數組的第一個元素是要執行的命令往后依次都是命令的參數,envp中是name=value形式的環境變量設置,如果子進程要繼承當前進程的環境時是null。

?

1?不正確的調用exitValue

Java代碼??
  • public?class?BadExecJavac?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????try?{??
  • ????????????Runtime?rt?=?Runtime.getRuntime();??
  • ????????????Process?proc?=?rt.exec("java");??
  • ????????????int?exitVal?=?proc.exitValue();??
  • ????????????System.out.println("Process?exitValue:?"?+?exitVal);??
  • ????????}?catch?(Throwable?t)?{??
  • ????????????t.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ?

    輸出

    Java代碼??
  • java.lang.IllegalThreadStateException:?process?has?not?exited??
  • ????at?java.lang.ProcessImpl.exitValue(Native?Method)??
  • ????at?BadExecJavac.main(BadExecJavac.java:26)??
  • ??

    錯誤分析:

    主要問題就是錯誤的調用了exitValue來取得外部命令的返回值。因為exitValue方法是非阻塞的,在調用這個方法時外部命令并沒有返回所以引起異常。阻塞形式的方法是waitFor,它會一直等待外部命令執行完畢,然后返回執行的結果。

    當你在一個Process上調用waitFor方法時,當前線程是阻塞的,如果外部命令無法執行結束,那么你的線程就會一直阻塞下去,這種意外會影響我們程序的執行。所以在我們不能判斷外部命令什么時候執行完畢而我們的程序還需要繼續執行的情況下,我們就應該循環的使用exitValue來取得外部命令的返回狀態,并在外部命令返回時作出相應的處理。

    ?

    2不正確的調用waitFor

    ?

    Java代碼??
  • 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();??
  • ????????}??
  • ????}??
  • }??
  • ? ? ? ?不幸的是,這個程序也無法執行完成,它沒有輸出但卻一直懸在那里!這是為什么那?

    ?

    JDK文檔中的解釋:因為本地的系統對標準輸入和輸出所提供的緩沖池有效,所以錯誤的對標準輸出快速的寫入和從標準輸入快速的讀入都有可能造成子進程的鎖,甚至死鎖。

    JDK僅僅說明為什么問題會發生,卻并沒有說明這個問題怎么解決。

    解決方法就是:執行完外部命令后我們要控制好Process的所有輸入和輸出(視情況而定),//在這個例子里邊因為調用的是Javac,而他在沒有參數的情況下會將提示信息輸出到標準出錯,所以在下面的程序中我們要對此進行處理。

    ?

    3?一種可接受的調用方式

    Java代碼??
  • 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></error>");??
  • ????????????while?((line?=?br.readLine())?!=?null)??
  • ????????????????System.out.println(line);??
  • ????????????System.out.println("");??
  • ????????????int?exitVal?=?proc.waitFor();??
  • ????????????System.out.println("Process?exitValue:?"?+?exitVal);??
  • ????????}?catch?(Throwable?t)?{??
  • ????????????t.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • 輸出:

    Java代碼??
  • <error></error>??
  • Usage:?javac?<options></options>?<source?files=""></source>??
  • ??
  • ...??
  • ??
  • Process?exitValue:?2??
  • ??結果分析:

    ?

    出來了結果。

    為了處理好外部命令大量輸出的情況,你要確保你的程序處理好外部命令所需要的輸入或者輸出。

    ?

    4?調用認為是可執行程序的時候容易發生的錯誤

    Java代碼??
  • public?class?BadExecWinDir?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????try?{??
  • ????????????Runtime?rt?=?Runtime.getRuntime();??
  • ????????????Process?proc?=?rt.exec("dir");??
  • ????????????InputStream?stdin?=?proc.getInputStream();??
  • ????????????InputStreamReader?isr?=?new?InputStreamReader(stdin);??
  • ????????????BufferedReader?br?=?new?BufferedReader(isr);??
  • ????????????String?line?=?null;??
  • ????????????System.out.println("<output></output>");??
  • ????????????while?((line?=?br.readLine())?!=?null)??
  • ????????????????System.out.println(line);??
  • ????????????System.out.println("");??
  • ????????????int?exitVal?=?proc.waitFor();??
  • ????????????System.out.println("Process?exitValue:?"?+?exitVal);??
  • ????????}?catch?(Throwable?t)?{??
  • ????????????t.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ?

    輸出:

    Java代碼??
  • java.io.IOException:?Cannot?run?program?"dir":?CreateProcess?error=2,?...??
  • ????at?java.lang.ProcessBuilder.start(ProcessBuilder.java:460)??
  • ????at?java.lang.Runtime.exec(Runtime.java:593)??
  • ????at?java.lang.Runtime.exec(Runtime.java:431)??
  • ????at?java.lang.Runtime.exec(Runtime.java:328)??
  • ????at?BadExecWinDir.main(BadExecWinDir.java:29)??
  • ??原因分析:

    ?

    因為dir命令是由windows中的解釋器解釋的,直接執行dir時無法找到dir.exe這個命令,所以會出現文件未找到這個2的錯誤。如果我們要執行這樣的命令,就要先根據操作系統的不同執行不同的解釋程序command.com?或者cmd.exe。

    ?

    5 window執行的良好示例

    Java代碼??
  • public?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();??
  • ????????}??
  • ????}??
  • }??
  • Java代碼??
  • public?class?GoodWindowsExec?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????if?(args.length?<?1)?{??
  • ????????????System.out.println("USAGE:?java?GoodWindowsExec?<cmd></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();??
  • ????????}??
  • ????}??
  • }??
  • ?

    輸出:

    ?

    ExitValue: 0

    ?

    原因分析:

    就是cmd.exe /C +一個windows中注冊了后綴的文檔名,windows會自動地調用相關的程序來打開這個文檔。

    不要假設你執行的程序是可執行的程序,要清楚自己的程序是單獨可執行的還是被解釋的,?這里還有一點,就是得到process的輸出的方式是getInputStream,這是因為我們要從Java?程序的角度來看,外部程序的輸出對于Java來說就是輸入,反之亦然。

    ?

    ?

    6?不良好的重定向命令輸出

    錯誤的認為exec方法會接受所有你在命令行或者Shell中輸入并接受的字符串。這些錯誤主要出現在命令作為參數的情況下,程序員錯誤的將所有命令行中可以輸入的參數命令加入到exec中。下面的例子中就是一個程序員想重定向一個命令的輸出。

    Java代碼??
  • public?class?BadWinRedirect?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????try?{??
  • ????????????Runtime?rt?=?Runtime.getRuntime();??
  • ????????????Process?proc?=?rt.exec("java?jecho?'Hello?World'?>?test.txt");??
  • ????????????//?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();??
  • ????????}??
  • ????}??
  • }??
  • ?

    程序員的本意是將Hello World這個輸入重訂向到一個文本文件中,但是這個文件并沒有生成,jecho僅僅是將命令行中的參數輸出到標準輸出中,用戶覺得可以像dos中重定向一樣將輸出重定向到一個文件中,但這并不能實現,用戶錯誤的將exec認為是一個shell解釋器,但它并不是,如果你想將一個程序的輸出重定向到其他的程序中,你必須用程序來實現他。可用java.io中的包。

    ?

    7?良好的重定向輸出示例

    Java代碼??
  • public?class?StreamGobbler?extends?Thread?{??
  • ????InputStream?is;??
  • ????String??????type;??
  • ????OutputStream?os;??
  • ????StreamGobbler(InputStream?is,?String?type)?{??
  • ????????this(is,?type,?null);??
  • ????}??
  • ????StreamGobbler(InputStream?is,?String?type,?OutputStream?redirect)?{??
  • ????????this.is?=?is;??
  • ????????this.type?=?type;??
  • ????????this.os?=?redirect;??
  • ????}??
  • ????public?void?run()?{??
  • ????????try?{??
  • ????????????PrintWriter?pw?=?null;??
  • ????????????if?(os?!=?null)??
  • ????????????????pw?=?new?PrintWriter(os);??
  • ????????????InputStreamReader?isr?=?new?InputStreamReader(is);??
  • ????????????BufferedReader?br?=?new?BufferedReader(isr);??
  • ????????????String?line?=?null;??
  • ????????????while?((line?=?br.readLine())?!=?null)?{??
  • ????????????????if?(pw?!=?null)??
  • ????????????????????pw.println(line);??
  • ????????????????System.out.println(type?+?">"?+?line);??
  • ????????????}??
  • ????????????if?(pw?!=?null)??
  • ????????????????pw.flush();??
  • ????????}?catch?(IOException?ioe)?{??
  • ????????????ioe.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • Java代碼??
  • public?class?GoodWinRedirect?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????args?=?new?String[1];??
  • ????????args[0]="g:\\out.txt";??
  • ????????if?(args.length?<?1)?{??
  • ????????????System.out.println("USAGE?java?GoodWinRedirect?<outputfile></outputfile>");??
  • ????????????System.exit(1);??
  • ????????}??
  • ????????try?{??
  • ????????????FileOutputStream?fos?=?new?FileOutputStream(args[0]);??
  • ????????????Runtime?rt?=?Runtime.getRuntime();??
  • ????????????Process?proc?=?rt.exec("java?jecho?'Hello?World'");??
  • ????????????//?any?error?message???
  • ????????????StreamGobbler?errorGobbler?=?new?StreamGobbler(proc.getErrorStream(),?"ERROR");??
  • ????????????//?any?output???
  • ????????????StreamGobbler?outputGobbler?=?new?StreamGobbler(proc.getInputStream(),?"OUTPUT",?fos);??
  • ????????????//?kick?them?off??
  • ????????????errorGobbler.start();??
  • ????????????outputGobbler.start();??
  • ????????????//?any?error?????
  • ????????????int?exitVal?=?proc.waitFor();??
  • ????????????System.out.println("ExitValue:?"?+?exitVal);??
  • ????????????fos.flush();??
  • ????????????fos.close();??
  • ????????}?catch?(Throwable?t)?{??
  • ????????????t.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ?

    ?

    8?總結

    總結了幾條規則,防止我們在進行Runtime.exec()調用時出現錯誤。

    ?

    • 在一個外部進程執行完之前你不能得到他的退出狀態
    • 在你的外部程序開始執行的時候你必須馬上控制輸入、輸出、出錯這些流。
    • 你必須用Runtime.exec()去執行程序
    • 你不能象命令行一樣使用Runtime.exec()。

    ?

    9?問答

    問:為什么Runtime.exec("ls")沒有任何輸出??

    答:調用Runtime.exec方法將產生一個本地的進程,并返回一個Process子類的實例,該實例可用于控制進程或取得進程的相關信息。

    由于調用Runtime.exec方法所創建的子進程沒有自己的終端或控制臺,因此該子進程的標準IO(如stdin,stdou,stderr)都通過Process.getOutputStream(),Process.getInputStream(),Process.getErrorStream()方法重定向給它的父進程了。用戶需要用這些stream來向子進程輸入數據或獲取子進程的輸出。所以正確執行Runtime.exec("ls")的例程如下:?

    Java代碼??
  • try?{??
  • ????Process?process?=?Runtime.getRuntime().exec(command);??
  • ????InputStreamReader?ir?=?new?InputStreamReader(process.getInputStream());??
  • ????LineNumberReader?input?=?new?LineNumberReader(ir);??
  • ????String?line;??
  • ????while?((line?=?input.readLine())?!=?null)??
  • ????????System.out.println(line);??
  • }?catch?(java.io.IOException?e)?{??
  • ????System.err.println("IOException?"?+?e.getMessage());??
  • }?
  • (原文地址:http://jiangshuiy.iteye.com/blog/1674235)

    轉載于:https://www.cnblogs.com/jianyungsun/p/7297381.html

    總結

    以上是生活随笔為你收集整理的[转]Java中Runtime.exec的一些事的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: www.啪| 日日躁狠狠躁 | 黄色综合网 | 国产草逼视频 | 四虎国产在线观看 | 尤物193.com | 国产高清在线视频 | 999毛片| 176精品免费| 中文字幕无线码 | 国产成人欧美一区二区三区91 | 视频二区在线观看 | 男女网站在线观看 | 色男人在线 | 97超碰站 | 天堂色区 | 亚洲天堂自拍偷拍 | 亚洲色图视频在线 | 国产精品视频自拍 | 中文字幕日韩精品亚洲一区小树林 | 精品人妻无码专区视频 | 欧美91视频 | 成人精品视频一区 | 天天操人人干 | 色屁屁www影院免费观看入口 | 国产在线视频网 | 富婆如狼似虎找黑人老外 | 亚洲一区二区日韩欧美 | 在线日韩欧美 | 欲色av| 亚洲欧美日韩一区在线观看 | 手机电影在线观看 | 奇米中文字幕 | 伊人超碰在线 | 免费av网页 | 亚洲免费精品视频 | 亚洲经典久久 | 国产男女猛烈无遮挡 | 嫩草导航| caoprom在线| 天天综合色 | 国产日韩欧美精品一区 | 真人真事免费毛片 | 99在线视频精品 | 亚洲视频四区 | 91麻豆国产在线 | 国产精品精 | 九九爱精品 | 美乳人妻一区二区三区 | 国产一区二区三区影视 | 欧美一本在线 | 午夜av在线免费观看 | 奇米狠狠 | 中国少妇色 | 免费美女视频网站 | 日韩欧美精品一区二区三区 | 特黄aaaaaaaaa毛片免费视频 | 国产精品美女高潮无套 | 法国空姐电影在线观看 | 国产专区第一页 | 亚洲一级二级三级 | 免费网站av | 爱爱网站视频 | 98在线视频| 国产精品12p | 久久噜噜色综合一区二区 | 欧美日韩一区二区三区四区 | 鲁一鲁啪一啪 | 99久久久无码国产精品性色戒 | 中文字幕av一区二区三区谷原希美 | www.日韩| 色呦网站 | 国产夫妇交换聚会群4p | 青草视频在线看 | 日本最黄网站 | 狠狠干2019| 绯色av一区二区 | 国产a级精品 | 午夜极品视频 | 超碰免费观看 | 影音先锋波多野结衣 | 人体内射精一区二区三区 | 亚洲欧美日韩在线一区二区 | 成人av在线资源 | 中国黄色一级视频 | 成人免费视 | 天堂在线中文在线 | 国产精品国产三级国产Av车上的 | 91免费视频网 | 一起操在线观看 | 日本男人天堂网 | 黄页网站免费观看 | 天天插天天干天天操 | 青青久久av北条麻妃黑人 | 亚洲手机av | 丁香综合 | 在线中文字幕网站 | 超碰在线99 | 日本a级片在线播放 |