Java創(chuàng)建進(jìn)程
1 進(jìn)程的概念 1
1.1 進(jìn)程的概念 1
1.2 進(jìn)程的特征 1
1.3 進(jìn)程與線程區(qū)別 1
2 進(jìn)程的創(chuàng)建 1
2.1 JAVA進(jìn)程的創(chuàng)建 1
2.1.1 ProcessBuilder 2
2.1.2 Runtime 3
2.1.3 Process 4
2.2 實(shí)例 5
2.2.1 創(chuàng)建子進(jìn)程 5
2.2.2 進(jìn)程阻塞問題 7
2.2.3 在java中執(zhí)行java程序 11
1 進(jìn)程的概念
1.1 進(jìn)程的概念
進(jìn)程是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ);是一個(gè)正在執(zhí)行的程序;計(jì)算機(jī)中正在運(yùn)行的程序?qū)嵗?;可以分配給處理器并由處理器執(zhí)行的一個(gè)實(shí)體;由單一順序的執(zhí)行顯示,一個(gè)當(dāng)前狀態(tài)和一組相關(guān)的系統(tǒng)資源所描述的活動(dòng)單元。
第一,進(jìn)程是一個(gè)實(shí)體。每一個(gè)進(jìn)程都有它自己的地址空間,一般情況下,包括文本區(qū)域(text region)、數(shù)據(jù)區(qū)域(data region)和堆棧(stack region)。文本區(qū)域存儲(chǔ)處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲(chǔ)變量和進(jìn)程執(zhí)行期間使用的動(dòng)態(tài)分配的內(nèi)存;堆棧區(qū)域存儲(chǔ)著活動(dòng)過程調(diào)用的指令和本地變量。
第 二,進(jìn)程是一個(gè)“執(zhí)行中的程序”。程序是一個(gè)沒有生命的實(shí)體,只有處理器賦予程序生命時(shí),它才能成為一個(gè)活動(dòng)的實(shí)體,我們稱其為進(jìn)程。
1.2 進(jìn)程的特征
動(dòng)態(tài)性:進(jìn)程的實(shí)質(zhì)是程序在多道程序系統(tǒng)中的一次執(zhí)行過程,進(jìn)程是動(dòng)態(tài)產(chǎn)生,動(dòng)態(tài)消亡的。
并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行
獨(dú)立性:進(jìn)程是一個(gè)能獨(dú)立運(yùn)行的基本單位,同時(shí)也是系統(tǒng)分配資源和調(diào)度的獨(dú)立單位;
異步性:由于進(jìn)程間的相互制約,使進(jìn)程具有執(zhí)行的間斷性,即進(jìn)程按各自獨(dú)立的、不可預(yù)知的速度向前推進(jìn)
結(jié)構(gòu)特征:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。
多個(gè)不同的進(jìn)程可以包含相同的程序:一個(gè)程序在不同的數(shù)據(jù)集里就構(gòu)成不同的進(jìn)程,能得到不同的結(jié)果;但是執(zhí)行過程中,程序不能發(fā)生改變。
1.3 進(jìn)程與線程區(qū)別
進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影 響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程 序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)
程。
2 進(jìn)程的創(chuàng)建
2.1 Java進(jìn)程的創(chuàng)建
Java提供了兩種方法用來啟動(dòng)進(jìn)程或其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法
2.1.1 ProcessBuilder
ProcessBuilder類是J2SE 1.5在java.lang中新添加的一個(gè)新類,此類用于創(chuàng)建操作系統(tǒng)進(jìn)程,它提供一種啟動(dòng)和管理進(jìn)程(也就是應(yīng)用程序)的方法。在J2SE 1.5之前,都是由Process類處來實(shí)現(xiàn)進(jìn)程的控制管理。
每個(gè) ProcessBuilder 實(shí)例管理一個(gè)進(jìn)程屬性集。start() 方法利用這些屬性創(chuàng)建一個(gè)新的 Process 實(shí)例。start() 方法可以從同一實(shí)例重復(fù)調(diào)用,以利用相同的或相關(guān)的屬性創(chuàng)建新的子進(jìn)程。
每個(gè)進(jìn)程生成器管理這些進(jìn)程屬性:
命令 是一個(gè)字符串列表,它表示要調(diào)用的外部程序文件及其參數(shù)(如果有)。在此,表示有效的操作系統(tǒng)命令的字符串列表是依賴于系統(tǒng)的。例如,每一個(gè)總體變量,通常都要成為此列表中的元素,但有一些操作系統(tǒng),希望程序能自己標(biāo)記命令行字符串——在這種系統(tǒng)中,Java 實(shí)現(xiàn)可能需要命令確切地包含這兩個(gè)元素。
環(huán)境 是從變量 到值 的依賴于系統(tǒng)的映射。初始值是當(dāng)前進(jìn)程環(huán)境的一個(gè)副本(請(qǐng)參閱 System.getenv())。
工作目錄。默認(rèn)值是當(dāng)前進(jìn)程的當(dāng)前工作目錄,通常根據(jù)系統(tǒng)屬性 user.dir 來命名。
redirectErrorStream 屬性。最初,此屬性為 false,意思是子進(jìn)程的標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出被發(fā)送給兩個(gè)獨(dú)立的流,這些流可以通過 Process.getInputStream() 和 Process.getErrorStream() 方法來訪問。如果將值設(shè)置為 true,標(biāo)準(zhǔn)錯(cuò)誤將與標(biāo)準(zhǔn)輸出合并。這使得關(guān)聯(lián)錯(cuò)誤消息和相應(yīng)的輸出變得更容易。在此情況下,合并的數(shù)據(jù)可從
Process.getInputStream() 返回的流讀取,而從 Process.getErrorStream() 返回的流讀取將直接到達(dá)文件尾。
修改進(jìn)程構(gòu)建器的屬性將影響后續(xù)由該對(duì)象的 start() 方法啟動(dòng)的進(jìn)程,但從不會(huì)影響以前啟動(dòng)的進(jìn)程或 Java 自身的進(jìn)程。大多數(shù)錯(cuò)誤檢查由 start() 方法執(zhí)行??梢孕薷膶?duì)象的狀態(tài),但這樣 start() 將會(huì)失敗。例如,將命令屬性設(shè)置為一個(gè)空列表將不會(huì)拋出異常,除非包含了 start()。
注意,此類不是同步的。如果多個(gè)線程同時(shí)訪問一個(gè) ProcessBuilder,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了其中一個(gè)屬性,它必須 保持外部同步。
Java代碼 
-
構(gòu)造方法摘要
-
ProcessBuilder(List<String> command)
-
利用指定的操作系統(tǒng)程序和參數(shù)構(gòu)造一個(gè)進(jìn)程生成器。
-
ProcessBuilder(String... command)
-
利用指定的操作系統(tǒng)程序和參數(shù)構(gòu)造一個(gè)進(jìn)程生成器。
-
-
方法摘要
-
List<String> command()
-
返回此進(jìn)程生成器的操作系統(tǒng)程序和參數(shù)。
-
ProcessBuilder command(List<String> command)
-
設(shè)置此進(jìn)程生成器的操作系統(tǒng)程序和參數(shù)。
-
ProcessBuilder command(String... command)
-
設(shè)置此進(jìn)程生成器的操作系統(tǒng)程序和參數(shù)。
-
File directory()
-
返回此進(jìn)程生成器的工作目錄。
-
ProcessBuilder directory(File directory)
-
設(shè)置此進(jìn)程生成器的工作目錄。
-
Map<String,String> environment()
-
返回此進(jìn)程生成器環(huán)境的字符串映射視圖。
-
boolean redirectErrorStream()
-
通知進(jìn)程生成器是否合并標(biāo)準(zhǔn)錯(cuò)誤和標(biāo)準(zhǔn)輸出。
-
ProcessBuilder redirectErrorStream(boolean redirectErrorStream)
-
設(shè)置此進(jìn)程生成器的 redirectErrorStream 屬性。
-
Process start()
-
使用此進(jìn)程生成器的屬性啟動(dòng)一個(gè)新進(jìn)程。
2.1.2 Runtime
每個(gè) Java 應(yīng)用程序都有一個(gè) Runtime 類實(shí)例,使應(yīng)用程序能夠與其運(yùn)行的環(huán)境相連接??梢酝ㄟ^ getRuntime 方法獲取當(dāng)前運(yùn)行時(shí)。
應(yīng)用程序不能創(chuàng)建自己的 Runtime 類實(shí)例。但可以通過 getRuntime 方法獲取當(dāng)前Runtime運(yùn)行時(shí)對(duì)象的引用。一旦得到了一個(gè)當(dāng)前的Runtime對(duì)象的引用,就可以調(diào)用Runtime對(duì)象的方法去控制Java虛擬機(jī)的狀態(tài)和行為。
Java代碼 
-
void addShutdownHook(Thread hook)
-
注冊(cè)新的虛擬機(jī)來關(guān)閉掛鉤。
-
int availableProcessors()
-
向 Java 虛擬機(jī)返回可用處理器的數(shù)目。
-
Process exec(String command)
-
在單獨(dú)的進(jìn)程中執(zhí)行指定的字符串命令。
-
Process exec(String[] cmdarray)
-
在單獨(dú)的進(jìn)程中執(zhí)行指定命令和變量。
-
Process exec(String[] cmdarray, String[] envp)
-
在指定環(huán)境的獨(dú)立進(jìn)程中執(zhí)行指定命令和變量。
-
Process exec(String[] cmdarray, String[] envp, File dir)
-
在指定環(huán)境和工作目錄的獨(dú)立進(jìn)程中執(zhí)行指定的命令和變量。
-
Process exec(String command, String[] envp)
-
在指定環(huán)境的單獨(dú)進(jìn)程中執(zhí)行指定的字符串命令。
-
Process exec(String command, String[] envp, File dir)
-
在有指定環(huán)境和工作目錄的獨(dú)立進(jìn)程中執(zhí)行指定的字符串命令。
-
void exit(int status)
-
通過啟動(dòng)虛擬機(jī)的關(guān)閉序列,終止當(dāng)前正在運(yùn)行的 Java 虛擬機(jī)。
-
long freeMemory()
-
返回 Java 虛擬機(jī)中的空閑內(nèi)存量。
-
void gc()
-
運(yùn)行垃圾回收器。
-
InputStream getLocalizedInputStream(InputStream in)
-
已過時(shí)。 從 JDK 1.1 開始,將本地編碼字節(jié)流轉(zhuǎn)換為 Unicode 字符流的首選方法是使用 InputStreamReader 和 BufferedReader 類。
-
OutputStream getLocalizedOutputStream(OutputStream out)
-
已過時(shí)。 從 JDK 1.1 開始,將 Unicode 字符流轉(zhuǎn)換為本地編碼字節(jié)流的首選方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 類。
-
static Runtime getRuntime()
-
返回與當(dāng)前 Java 應(yīng)用程序相關(guān)的運(yùn)行時(shí)對(duì)象。
-
void halt(int status)
-
強(qiáng)行終止目前正在運(yùn)行的 Java 虛擬機(jī)。
-
void load(String filename)
-
加載作為動(dòng)態(tài)庫的指定文件名。
-
void loadLibrary(String libname)
-
加載具有指定庫名的動(dòng)態(tài)庫。
-
long maxMemory()
-
返回 Java 虛擬機(jī)試圖使用的最大內(nèi)存量。
-
boolean removeShutdownHook(Thread hook)
-
取消注冊(cè)某個(gè)先前已注冊(cè)的虛擬機(jī)關(guān)閉掛鉤。
-
void runFinalization()
-
運(yùn)行掛起 finalization 的所有對(duì)象的終止方法。
-
static void runFinalizersOnExit(boolean value)
-
已過時(shí)。 此方法本身具有不安全性。它可能對(duì)正在使用的對(duì)象調(diào)用終結(jié)方法,而其他線程正在操作這些對(duì)象,從而導(dǎo)致不正確的行為或死鎖。
-
long totalMemory()
-
返回 Java 虛擬機(jī)中的內(nèi)存總量。
-
void traceInstructions(boolean on)
-
啟用/禁用指令跟蹤。
-
void traceMethodCalls(boolean on)
-
啟用/禁用方法調(diào)用跟蹤。
2.1.3 Process
不管通過那種方法啟動(dòng)進(jìn)程后,都會(huì)返回一個(gè)Process類的實(shí)例代表啟動(dòng)的進(jìn)程,該實(shí)例可用來控制進(jìn)程并獲得相關(guān)信息。Process 類提供了執(zhí)行從進(jìn)程輸入、執(zhí)行輸出到進(jìn)程、等待進(jìn)程完成、檢查進(jìn)程的退出狀態(tài)以及銷毀(殺掉)進(jìn)程的方法:
Java代碼 
-
void destroy()
-
殺掉子進(jìn)程。
-
一般情況下,該方法并不能殺掉已經(jīng)啟動(dòng)的進(jìn)程,不用為好。
-
int exitValue()
-
返回子進(jìn)程的出口值。
-
只有啟動(dòng)的進(jìn)程執(zhí)行完成、或者由于異常退出后,exitValue()方法才會(huì)有正常的返回值,否則拋出異常。
-
InputStream getErrorStream()
-
獲取子進(jìn)程的錯(cuò)誤流。
-
如果錯(cuò)誤輸出被重定向,則不能從該流中讀取錯(cuò)誤輸出。
-
InputStream getInputStream()
-
獲取子進(jìn)程的輸入流。
-
可以從該流中讀取進(jìn)程的標(biāo)準(zhǔn)輸出。
-
OutputStream getOutputStream()
-
獲取子進(jìn)程的輸出流。
-
寫入到該流中的數(shù)據(jù)作為進(jìn)程的標(biāo)準(zhǔn)輸入。
-
int waitFor()
-
導(dǎo)致當(dāng)前線程等待,如有必要,一直要等到由該 Process 對(duì)象表示的進(jìn)程已經(jīng)終止。
通過該類提供的方法,可以實(shí)現(xiàn)與啟動(dòng)的進(jìn)程之間通信,達(dá)到交互的目的。
2.2 實(shí)例
2.2.1 創(chuàng)建子進(jìn)程
要?jiǎng)?chuàng)建子進(jìn)程可以通過使用使用ProcessBuilder的start()方法和Runtime的exec()方法。
(1)Runtime.exec()
Java代碼 
-
import java.io.BufferedReader;
-
import java.io.File;
-
import java.io.InputStreamReader;
-
-
public class Test1 {
-
public static void main(String[] args) {
-
try {
-
Process p = null;
-
String line = null;
-
BufferedReader stdout = null;
-
-
//list the files and directorys under C:\
-
p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));
-
stdout = new BufferedReader(new InputStreamReader(p
-
.getInputStream()));
-
while ((line = stdout.readLine()) != null) {
-
System.out.println(line);
-
}
-
stdout.close();
-
-
//echo the value of NAME
-
p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[] {"NAME=TEST"});
-
stdout = new BufferedReader(new InputStreamReader(p
-
.getInputStream()));
-
while ((line = stdout.readLine()) != null) {
-
System.out.println(line);
-
}
-
stdout.close();
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
(2)ProcessBuilder
Java代碼 
-
import java.io.BufferedReader;
-
import java.io.File;
-
import java.io.InputStreamReader;
-
import java.util.ArrayList;
-
import java.util.List;
-
-
public class Test2 {
-
public static void main(String[] args) {
-
try {
-
List<String> list = new ArrayList<String>();
-
ProcessBuilder pb = null;
-
Process p = null;
-
String line = null;
-
BufferedReader stdout = null;
-
-
//list the files and directorys under C:\
-
list.add("CMD.EXE");
-
list.add("/C");
-
list.add("dir");
-
pb = new ProcessBuilder(list);
-
pb.directory(new File("C:\\"));
-
p = pb.start();
-
-
stdout = new BufferedReader(new InputStreamReader(p
-
.getInputStream()));
-
while ((line = stdout.readLine()) != null) {
-
System.out.println(line);
-
}
-
stdout.close();
-
-
//echo the value of NAME
-
pb = new ProcessBuilder();
-
pb.command(new String[] {"CMD.exe", "/C", "echo %NAME%"});
-
pb.environment().put("NAME", "TEST");
-
p = pb.start();
-
-
stdout = new BufferedReader(new InputStreamReader(p
-
.getInputStream()));
-
while ((line = stdout.readLine()) != null) {
-
System.out.println(line);
-
}
-
stdout.close();
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
從啟動(dòng)其他程序的Java進(jìn)程看,已啟動(dòng)的其他程序輸出就是一個(gè)普通的輸入流,可以通過getInputStream()和getErrorStream來獲取。對(duì)于一般輸出文本的進(jìn)程來說,可以將InputStream封裝成BufferedReader,然后就可以一行一行的對(duì)進(jìn)程的標(biāo)準(zhǔn)輸出進(jìn)行處理。
通常,一個(gè)程序/進(jìn)程在執(zhí)行結(jié)束后會(huì)向操作系統(tǒng)返回一個(gè)整數(shù)值,0一般代表執(zhí)行成功,非0表示執(zhí)行出現(xiàn)問題。有兩種方式可以用來獲取進(jìn)程的返回值。一是利用waitFor(),該方法是阻塞的,執(zhí)導(dǎo)進(jìn)程執(zhí)行完成后再返回。該方法返回一個(gè)代表進(jìn)程返回值的整數(shù)值。另一個(gè)方法是調(diào)用exitValue()方法,該方法是非阻塞的,調(diào)用立即返回。但是如果進(jìn)程沒有執(zhí)行完成,則拋出異常。
2.2.2 進(jìn)程阻塞問題
由Process代表的進(jìn)程在某些平臺(tái)上有時(shí)候并不能很好的工作,特別是在對(duì)代表進(jìn)程的標(biāo)準(zhǔn)輸入流、輸出流和錯(cuò)誤輸出進(jìn)行操作時(shí),如果使用不慎,有可能導(dǎo)致進(jìn)程阻塞,甚至死鎖。
如果將以上事例中的從標(biāo)準(zhǔn)輸出重讀取信息的語句修改為從錯(cuò)誤輸出流中讀?。?nbsp;
stdout = new BufferedReader(new InputStreamReader(p.getErrorStream()));
那么程序?qū)l(fā)生阻塞,不能執(zhí)行完成,而是hang在那里。
當(dāng)進(jìn)程啟動(dòng)后,就會(huì)打開標(biāo)準(zhǔn)輸出流和錯(cuò)誤輸出流準(zhǔn)備輸出,當(dāng)進(jìn)程結(jié)束時(shí),就會(huì)關(guān)閉他們。在以上例子中,錯(cuò)誤輸出流沒有數(shù)據(jù)要輸出,標(biāo)準(zhǔn)輸出流中有數(shù)據(jù)輸出。由于標(biāo)準(zhǔn)輸出流中的數(shù)據(jù)沒有被讀取,進(jìn)程就不會(huì)結(jié)束,錯(cuò)誤輸出流也就不會(huì)被關(guān)閉,因此在調(diào)用readLine()方法時(shí),整個(gè)程序就會(huì)被阻塞。為了解決這個(gè)問題,可以根據(jù)輸出的實(shí)際先后,先讀取標(biāo)準(zhǔn)輸出流,然后讀取錯(cuò)誤輸出流。
但是,很多時(shí)候不能很明確的知道輸出的先后,特別是要操作標(biāo)準(zhǔn)輸入的時(shí)候,情況就會(huì)更為復(fù)雜。這時(shí)候可以采用線程來對(duì)標(biāo)準(zhǔn)輸出、錯(cuò)誤輸出和標(biāo)準(zhǔn)輸入進(jìn)行分別處理,根據(jù)他們之間在業(yè)務(wù)邏輯上的關(guān)系決定讀取那個(gè)流或者寫入數(shù)據(jù)。
針對(duì)標(biāo)準(zhǔn)輸出流和錯(cuò)誤輸出流所造成的問題,可以使用ProcessBuilder的redirectErrorStream()方法將他們合二為一,這時(shí)候只要讀取標(biāo)準(zhǔn)輸出的數(shù)據(jù)就可以了。
當(dāng)在程序中使用Process的waitFor()方法時(shí),特別是在讀取之前調(diào)用waitFor()方法時(shí),也有可能造成阻塞。可以用線程的方法來解決這個(gè)問題,也可以在讀取數(shù)據(jù)后,調(diào)用waitFor()方法等待程序結(jié)束。
總之,解決阻塞的方法應(yīng)該有兩種:
(1)使用ProcessBuilder類,利用redirectErrorStream方法將標(biāo)準(zhǔn)輸出流和錯(cuò)誤輸出流合二為一,在用start()方法啟動(dòng)進(jìn)程后,先從標(biāo)準(zhǔn)輸出中讀取數(shù)據(jù),然后調(diào)用waitFor()方法等待進(jìn)程結(jié)束。
如:
Java代碼 
-
import java.io.BufferedReader;
-
import java.io.File;
-
import java.io.InputStreamReader;
-
import java.util.ArrayList;
-
import java.util.List;
-
-
public class Test3 {
-
public static void main(String[] args) {
-
try {
-
List<String> list = new ArrayList<String>();
-
ProcessBuilder pb = null;
-
Process p = null;
-
String line = null;
-
BufferedReader stdout = null;
-
//list the files and directorys under C:\
-
list.add("CMD.EXE");
-
list.add("/C");
-
list.add("dir1");
-
pb = new ProcessBuilder(list);
-
pb.directory(new File("C:\\"));
-
//merge the error output with the standard output
-
pb.redirectErrorStream(true);
-
p = pb.start();
-
//read the standard output
-
stdout = new BufferedReader(new InputStreamReader(p
-
.getInputStream()));
-
while ((line = stdout.readLine()) != null) {
-
System.out.println(line);
-
}
-
int ret = p.waitFor();
-
System.out.println("the return code is " + ret);
-
stdout.close();
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
(2)使用線程
Java代碼 
-
import java.util.*;
-
import java.io.*;
-
-
class StreamWatch extends Thread {
-
InputStream is;
-
String type;
-
List<String> output = new ArrayList<String>();
-
boolean debug = false;
-
StreamWatch(InputStream is, String type) {
-
this(is, type, false);
-
}
-
-
StreamWatch(InputStream is, String type, boolean debug) {
-
this.is = is;
-
this.type = type;
-
this.debug = debug;
-
}
-
-
public void run() {
-
try {
-
PrintWriter pw = null;
-
InputStreamReader isr = new InputStreamReader(is);
-
BufferedReader br = new BufferedReader(isr);
-
String line = null;
-
while ((line = br.readLine()) != null) {
-
output.add(line);
-
if (debug)
-
System.out.println(type + ">" + line);
-
}
-
if (pw != null)
-
pw.flush();
-
} catch (IOException ioe) {
-
ioe.printStackTrace();
-
}
-
}
-
-
public List<String> getOutput() {
-
return output;
-
}
-
}
Java代碼 
-
public class Test5 {
-
public static void main(String args[]) {
-
try {
-
List<String> list = new ArrayList<String>();
-
ProcessBuilder pb = null;
-
Process p = null;
-
// list the files and directorys under C:\
-
list.add("CMD.EXE");
-
list.add("/C");
-
list.add("dir1");
-
pb = new ProcessBuilder(list);
-
pb.directory(new File("C:\\"));
-
p = pb.start();
-
-
// process error and output message
-
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
-
"ERROR");
-
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
-
"OUTPUT");
-
// start to watch
-
errorWatch.start();
-
outputWatch.start();
-
//wait for exit
-
int exitVal = p.waitFor();
-
//print the content from ERROR and OUTPUT
-
System.out.println("ERROR: " + errorWatch.getOutput());
-
System.out.println("OUTPUT: " + outputWatch.getOutput());
-
System.out.println("the return code is " + exitVal);
-
} catch (Throwable t) {
-
t.printStackTrace();
-
}
-
}
-
}
2.2.3 在java中執(zhí)行java程序
執(zhí)行一個(gè)Java程序的關(guān)鍵在于:
(1)知道JAVA虛擬機(jī)的位置,即java.exe或者java的路徑
(2)知道要執(zhí)行的java程序的位置
(3)知道該程序所依賴的其他類的位置
舉一個(gè)例子,一目了然。
(1)待執(zhí)行的Java類
Java代碼 
-
public class MyTest {
-
public static void main(String[] args) {
-
System.out.println("OUTPUT one");
-
System.out.println("OUTPUT two");
-
System.err.println("ERROR 1");
-
System.err.println("ERROR 2");
-
for(int i = 0; i < args.length; i++)
-
{
-
System.out.printf("args[%d] = %s.", i, args[i]);
-
}
-
}
-
}
(2)執(zhí)行該類的程序
Java代碼 
-
import java.util.*;
-
import java.io.*;
-
-
class StreamWatch extends Thread {
-
InputStream is;
-
String type;
-
List<String> output = new ArrayList<String>();
-
boolean debug = false;
-
-
StreamWatch(InputStream is, String type) {
-
this(is, type, false);
-
}
-
-
StreamWatch(InputStream is, String type, boolean debug) {
-
this.is = is;
-
this.type = type;
-
this.debug = debug;
-
}
-
-
public void run() {
-
try {
-
PrintWriter pw = null;
-
InputStreamReader isr = new InputStreamReader(is);
-
BufferedReader br = new BufferedReader(isr);
-
String line = null;
-
while ((line = br.readLine()) != null) {
-
output.add(line);
-
if (debug)
-
System.out.println(type + ">" + line);
-
}
-
if (pw != null)
-
pw.flush();
-
} catch (IOException ioe) {
-
ioe.printStackTrace();
-
}
-
}
-
-
public List<String> getOutput() {
-
return output;
-
}
-
}
Java代碼 
-
public class Test6 {
-
public static void main(String args[]) {
-
try {
-
List<String> list = new ArrayList<String>();
-
ProcessBuilder pb = null;
-
Process p = null;
-
-
String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
-
String classpath = System.getProperty("java.class.path");
-
// list the files and directorys under C:\
-
list.add(java);
-
list.add("-classpath");
-
list.add(classpath);
-
list.add(MyTest.class.getName());
-
list.add("hello");
-
list.add("world");
-
list.add("good better best");
-
-
pb = new ProcessBuilder(list);
-
p = pb.start();
-
-
System.out.println(pb.command());
-
// process error and output message
-
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
-
"ERROR");
-
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
-
"OUTPUT");
-
// start to watch
-
errorWatch.start();
-
outputWatch.start();
-
//wait for exit
-
int exitVal = p.waitFor();
-
//print the content from ERROR and OUTPUT
-
System.out.println("ERROR: " + errorWatch.getOutput());
-
System.out.println("OUTPUT: " + outputWatch.getOutput());
-
System.out.println("the return code is " + exitVal);
-
} catch (Throwable t) {
-
t.printStackTrace();
-
}
|