溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解java.lang.Runtime.exec的流輸入和流讀取

發(fā)布時(shí)間:2021-11-03 13:36:02 來源:億速云 閱讀:314 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“怎么理解java.lang.Runtime.exec的流輸入和流讀取”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么理解java.lang.Runtime.exec的流輸入和流讀取”吧!

什么是java.lang.Runtime

首先我們要明確一點(diǎn),什么是Java.lang.Runtime? 我們來看官方[->link<-]的描述:

" Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.

An application cannot create its own instance of this class. "

也就是說,Runtime是每個(gè)java-application運(yùn)行時(shí)有且僅有一個(gè)的當(dāng)前實(shí)例.允許Application接入當(dāng)前運(yùn)行環(huán)境.

我們?cè)賮砜纯碦untime的exec()方法:

" Executes the specified command in a separate process. "

這個(gè)方法可以讓我們?cè)谝粋€(gè)進(jìn)程中執(zhí)行指定的命令.其返回類型是Process類.

那么我們還需要來看一下Process類:

什么是java.lang.Process

什么是Java.lang.Process? 我們來看官方[->link<-]的描述:

"The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process."

也就是說這個(gè)類提供控制線程的方法.

我們?cè)賮砜纯碢rocess提供的獲取輸入流和輸出流的方法:

public abstract InputStream getInputStream()

"Returns the input stream connected to the normal output of the subprocess.
The stream obtains data piped from the standard output of the process represented by this Process object."
public abstract OutputStream getOutputStream()
"Returns the output stream connected to the normal input of the subprocess.
Output to the stream is piped into the standard input of the process represented by this Process object."

public abstract InputStream getErrorStream()

"Returns the input stream connected to the error output of the subprocess.
The stream obtains data piped from the error output of the process represented by this Process object."

到這里,我們就明白里其中的因果>從exec()返回的Process的對(duì)象中調(diào)用獲取流的方法.從而達(dá)到目的!

具體做法

在需要使用exec()去執(zhí)行命令并獲取返回值的時(shí)候,具體的做法是什么呢?

僅僅圍繞這個(gè)思路:"從exec()返回的Process的對(duì)象中調(diào)用獲取流的方法getXStream"

String s = null;
              Process p = Runtime
                      .getRuntime()
                      .exec(
                              new String[]{"/bin/sh",
                                          "-c",
                                          "java HelloWorld"},null,dir);
 
              BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
              BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
 
              //打印出輸出結(jié)果
              log.info("標(biāo)準(zhǔn)輸出命令");
              while ((s = stdInput.readLine()) != null) {
                    log.info(s);
              }
 
              log.info("標(biāo)準(zhǔn)錯(cuò)誤的輸出命令");
              while ((s = stdError.readLine()) != null) {
                    log.info(s);
              }

其中

dir 是我的HelloWorld.class的存放目錄,只能這樣用,請(qǐng)參照這篇

HelloWorld.java 的內(nèi)容是Sysotem.out.println打印幾行Hello World,此處沒有編譯,使用時(shí)應(yīng)注意.

怎么理解java.lang.Runtime.exec的流輸入和流讀取

到此,大功告成!

Runtime.exec 陷阱

該類java.lang.Runtime具有一個(gè)稱為的靜態(tài)方法getRuntime(),該方法檢索當(dāng)前的Java Runtime Environment。這是獲得對(duì)該Runtime對(duì)象的引用的唯一方法。使用該參考,您可以通過調(diào)用Runtime類的exec()方法來運(yùn)行外部程序。開發(fā)人員經(jīng)常調(diào)用此方法來啟動(dòng)瀏覽器,以顯示HTML的幫助頁面。

該exec()命令有四個(gè)重載版本:

public Process exec(String command);
public Process exec(String [] cmdArray);
public Process exec(String command, String [] envp);
public Process exec(String [] cmdArray, String [] envp);

對(duì)于這些方法中的每一個(gè),命令(可能還有一組參數(shù))都傳遞給特定于操作系統(tǒng)的函數(shù)調(diào)用。隨后,這將參考Process返回給Java VM的類來創(chuàng)建特定于操作系統(tǒng)的進(jìn)程(正在運(yùn)行的程序)。所述Process類是一個(gè)抽象類,因?yàn)橐粋€(gè)特定的子類Process存在于每個(gè)操作系統(tǒng)。

您可以將三個(gè)可能的輸入?yún)?shù)傳遞給這些方法:

  • 一個(gè)字符串,代表要執(zhí)行的程序和該程序的所有參數(shù)

  • 字符串?dāng)?shù)組,用于將程序與其參數(shù)分開

  • 一組環(huán)境變量

以形式傳遞環(huán)境變量name=value。如果exec()對(duì)程序及其參數(shù)使用單個(gè)字符串的版本,請(qǐng)注意,通過StringTokenizer類使用空格作為分隔符來解析該字符串。

IllegalThreadStateException

要執(zhí)行Java VM外部的進(jìn)程,我們使用exec()方法。要查看外部進(jìn)程返回的值,我們exitValue()。

如果外部過程尚未完成,則該exitValue()方法將拋出IllegalThreadStateException;。這就是該程序失敗的原因。盡管文檔中說明了這一事實(shí),但為什么不能等到此方法可以給出有效答案呢?

對(duì)該P(yáng)rocess類中可用的方法進(jìn)行更徹底的研究,就會(huì)發(fā)現(xiàn)waitFor()可以做到這一點(diǎn)的方法。實(shí)際上,waitFor()還會(huì)返回退出值,這意味著您將不會(huì)使用exitValue()和waitFor()彼此結(jié)合,而是會(huì)選擇一個(gè)或另一個(gè)。你會(huì)使用的唯一可能的時(shí)間exitValue(),而不是waitFor()會(huì)當(dāng)你不希望你的程序阻止等待外部過程中可能永遠(yuǎn)不會(huì)完成。與其使用該waitFor()方法,不如將一個(gè)被調(diào)用的布爾參數(shù)waitFor傳入該exitValue()方法以確定當(dāng)前線程是否應(yīng)等待。布爾值會(huì)更有利,因?yàn)閑xitValue()是此方法的更合適的名稱,兩個(gè)方法在不同條件下不必執(zhí)行相同的功能。這種簡(jiǎn)單的條件判別是輸入?yún)?shù)的領(lǐng)域。

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();
          }
    }
}
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();
          }
    }
}

因此,為避免此陷阱,請(qǐng)捕獲IllegalThreadStateException或等待該過程完成。

為什么Runtime.exec()掛起

由于某些本機(jī)平臺(tái)僅為標(biāo)準(zhǔn)輸入和輸出流提供有限的緩沖區(qū)大小,因此未能及時(shí)寫入子流程的輸入流或讀取子流程的輸出流可能導(dǎo)致子流程阻塞,甚至死鎖。

現(xiàn)在,讓我們關(guān)注JDK文檔并處理javac過程的輸出。當(dāng)您javac不帶任何參數(shù)運(yùn)行時(shí),它會(huì)生成一組用法語句,這些用法語句描述了如何運(yùn)行程序以及所有可用程序選項(xiàng)的含義。知道這將stderr流到流,您可以輕松地編寫一個(gè)程序以在等待進(jìn)程退出之前耗盡該流。清單4.3完成了該任務(wù)。盡管此方法行之有效,但這不是一個(gè)好的通用解決方案。因此,清單4.3的程序被命名為MediocreExecJavac;。它僅提供平庸的解決方案。更好的解決方案將同時(shí)清空標(biāo)準(zhǔn)錯(cuò)誤流和標(biāo)準(zhǔn)輸出流。最好的解決方案是同時(shí)清空這些流(稍后再說明)

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();
          }
    }
}

感謝各位的閱讀,以上就是“怎么理解java.lang.Runtime.exec的流輸入和流讀取”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)怎么理解java.lang.Runtime.exec的流輸入和流讀取這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI