Article From:https://www.cnblogs.com/runtimeexception/p/9968490.html

SunThe doc actually shows that there are other uses:

exec(String[] cmdarray, String[] envp, File dir)

Executes the specified command and arguments in a separate process with the specified environment and working directory.

That dir is the working directory of the calling program, which is actually very useful.

WindowsNext caller

Process proc =Runtime.getRuntime().exec("exefile");

LinuxThe next caller needs to change to the following format

Process proc =Runtime.getRuntime().exec("./exefile");

WindowsCall down system commands

String [] cmd={"cmd","/C","copy exe1 exe2"}; 
Process proc =Runtime.getRuntime().exec(cmd);

LinuxTo invoke system commands, change the format to the following

String [] cmd={"/bin/sh","-c","ln -s exe1 exe2"}; 
Process proc =Runtime.getRuntime().exec(cmd);

WindowsCall down system commands and pop up command line windows

String [] cmd={"cmd","/C","start copy exe1 exe2"}; 
Process proc =Runtime.getRuntime().exec(cmd);

LinuxTo call the system command and pop up the terminal window, change the format to the following

String [] cmd={"/bin/sh","-c","xterm -e ln -s exe1 exe2"};
Process proc =Runtime.getRuntime().exec(cmd);

There is also a working directory to set up the calling program.

Process proc =Runtime.getRuntime().exec("exeflie",null, new File("workpath"));

Of course, the best way to execute system commands is to write a bat file or shell script. Then call it, which is much simpler to modify and implement.

There is also a detailed article on how to display intercepted console output in JTextArea in Java programs.

 

JAVANow the main way to execute external commands is to call the SHELL of all platforms. CMD, LINUX or SHELL are used under WINDOWS. Here is a demonstration of a call to BAT files, and the results are displayed on the console.Other application classes. Description: A call to SHELL to execute the external program to get the output stream of the external program, read it back with the appropriate READER, and display it as OK. Here is the source program:

Copy Code ____________
import java.io.BufferedReader;    
import java.io.IOException;    
import java.io.InputStream;    
import java.io.InputStreamReader;    
   
public class JavaExeBat    
{    
    public static void main(String[] args)    
     {    
         Process p;    
        //test.batThe command in ipconfig/allString cmd= "c:\\ test test\ test. bat";Try{// Execution of ordersP = Runtime. getRuntime (). exec (cmd);// Output stream for command resultsInputStream FIS = P. getInputStream ();// Read with a read-output stream classInputStream Reader ISR = new InputStream Reader (fis);// Read lines with buffersBufferedReader br = new BufferedReader (isr);String line = null;/ /Until the end of readingWhile ((line = br. readLine ())! = null){SysTem. out. println (line);}}Catch (IOException){E. printStackTrace ();}}}
Copy Code ____________

 The results are as follows:

Copy Code ____________
Windows IP Configuration 

Host Name . . . . . . . . . . . . : Mickey 

Primary Dns Suffix . . . . . . . : 

Node Type . . . . . . . . . . . . : Unknown 

IP Routing Enabled. . . . . . . . : No 

WINS Proxy Enabled. . . . . . . . : No 

DNS Suffix Search List. . . . . . : domain 
Ethernet adapter Local connection:Connection-specific DNS Suffix.: DomainDescription.............. Broadcom NetXtreme Gigabit Ethernet
Copy Code ____________

 

Let’s start with the Runtime class, which is related to the JVM runtime environment. This class is Singleton. I said a few things that I thought were important.

1、Runtime.getRuntime()You can get the current JVM runtime environment, which is the only way to get the runtime environment in Java.

2、RuntimeMost of the other methods above are instance methods, which means that getRuntime methods are used every time a runtime call is made.

3、 RuntimeThe exit method in the System class is probably the only way to exit the current JVM, because I see that exit in the System class actually exits the JVM by calling Runtime. exit (). Here’s how Java returns to Runtime.The general rule of revaluation (mentioned later), 0 represents normal exit and non-zero represents abnormal termination, which is just Java’s rule, and there will always be some minor confusion in each operating system.

4、Runtime.addShutdownHook()Method can register a hook in the process of shutdown by JVM. The parameters of the method can be as long as a Thread instance is initialized but not executed. (Note that Thread in Java is inexpensive after execution.)

5、 When it comes to addShutdown Hook, you need to talk about the circumstances under which the JVM runs shutdown or abort. This is what the document says when the last non-sprite process exits or receives a user interrupt signal, user logout, systemWhen the exit method of shutdown and Runtime is called, the JVM will start the shutdown process. After the process starts, it will start all registered shutdown hooks in parallel.Lock). When the shutdown process starts, only by calling halt method can the shutdown process be aborted and the JVM exit.

When will the JVM abort out? First of all, when abort exits, the JVM stops running but does not necessarily shutdown. This is only when the JVM encounters SIGKILL signal or windows termination signal, local method.Internal errors, such as access to illegal addresses, can occur. In this case, there is no guarantee that the shutdown hook will be executed.

Now start reading this article, ha ha ha.

First of all, I want to talk about it.Runtime.exec() All overloads of the method. One thing to note here is the public process exec (String [] cmdArray, String [] envp); in this method, cmdArray is an executed command and parameter.The first element of the array is the parameters of the command. I personally feel that ENVP should be the same as the environment variable in execve in C. ENVP uses name = value.

<!—->1、 <!—->A terrible caller. The code is as follows. This program calls an external command with exec and checks its return value immediately with exitValue. Let’s see what happens.

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

 

A run of BadExecJavac produces:

E:classescomjavaworldjpitfallsarticle2>java BadExecJavac java.lang.IllegalThreadStateException: 
 process has not exited at java.lang.Win32Process.exitValue(Native Method) at BadExecJavac.main(BadExecJavac.java:13)

 

As you can see from the original text, the main problem here is that the exitValue is invoked incorrectly to get the return value of the external command (ha, I’ve made this mistake before), because the exitValue method is non-blocking. When the program invokes this method, the external command andThere is no return, so there is an exception. Here is another way to wait for the execution of the external command, which is the waitFor method. This method will block until the execution of the external command ends, and then return the result of the execution of the external command.Question, ah, anyway, I don’t care. I can pull it if I use it. But the author has a note here that exitValue also has many uses. Because when you call the waitFor method on a Process, the current thread is blocked if the external commandIf you can’t finish executing, then your thread will be blocked all the time. This kind of accident will affect the execution of our program. So when we can’t tell when the external command is finished and our program needs to continue executing, we should use exitValue circularly to obtain the external command.The return status of the Department command and the corresponding processing when the external command returns.

2、An improved program for exitValue

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

 Unfortunately, this program can’t be executed. It doesn’t output, but it hangs there all the time. Why is that?

JDKThis is explained in the document: because the local system is effective for the buffer pool provided by the standard input and output, fast writing of the standard output incorrectly and fast reading from the standard input may result in lock or even deadlock of the sub-process.

When the document was quoted, the author began to criticize it again. He said that JDK only explained why the problem happened, but did not explain how to solve it. This is indeed a problem. Next, the author tells us what he’s doing, that is, we have to control everything in Process after we have executed the external commands.Input and output (depending on the situation), in this case, because Javac is called, and he will output the prompt information to the standard error without parameters, so we need to deal with it in the following program.

Copy Code ____________
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></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();
        }
    }
}
Copy Code ____________

 The program runs as follows

Copy Code ____________
E:classescomjavaworldjpitfallsarticle2>java MediocreExecJavac <error></error> Usage: javac <options></options> <source files=""></source>

where <options></options> includes: -g Generate all debugging info -g:none
Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -O
Optimize; may hinder debugging or enlarge class files -nowarn Generate no warnings -verbose
Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath
Specify where to find user class files -sourcepath Specify where to find input source files -bootclasspath
Override location of bootstrap class files -extdirs <dirs></dirs>Override location of installed extensions -d <directory></directory>
Specify where to place generated class files -encoding <encoding></encoding>
Specify character encoding used by source files -target <release></release>
Generate class files for specific VM version
Process exitValue: 2
Copy Code ____________

 

Well, anyway, the results come out. The author concludes that in order to deal with the large output of external commands, you need to make sure that your program handles the input or output required by external commands.

Next topic, when we call an executable program that we think is easy to make mistakes (I just made this mistake tonight, when I have nothing to do this exercise)

Copy Code ____________
import java.util.*;
import java.io.*;

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

 

Copy Code ____________
A run of BadExecWinDir produces:

E:classescomjavaworldjpitfallsarticle2>java BadExecWinDir java.io.IOException: 
CreateProcess: dir error=2 at java.lang.Win32Process.create(Native Method) at java.lang.Win32Process.<init></init>
(Unknown Source) at java.lang.Runtime.execInternal(Native Method) at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source)
at BadExecWinDir.main(BadExecWinDir.java:12)
Copy Code ____________

 

To be honest, this mistake really bothers me. I think the reason why returning 2 to Windows should not find this file is that there may be only CMD command in Windows 2000, but dir command is not explainable by current environment variables. I don’t know.Look down slowly.

Hey, as the author thought, because the dir command is interpreted by the interpreter in windows, the dir. exe command can not be found when the dir is executed directly, so there will be an error that the file does not find this 2. If we want to carry out such an order, we have to base it onDifferent operating systems execute different interpreters command.com or cmd.exe.

The author has modified the above procedure.

Copy Code ____________
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></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
        }                                        
    }
}
Copy Code ____________

 

Copy Code ____________
Running GoodWindowsExec with the dir command generates:

E:classescomjavaworldjpitfallsarticle2>java GoodWindowsExec "dir *.java" 
Execing cmd.exe /C dir *.java OUTPUT> Volume in drive E has no label. OUTPUT>
Volume Serial Number is 5C5F-0CC9 OUTPUT> OUTPUT> Directory of E:classescomjavaworldjpitfallsarticle2 OUTPUT>
OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java OUTPUT>10/24/00 08:45p 488
BadExecJavac.java OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java OUTPUT>10/24/00 09:13p 930
BadExecWinDir.java OUTPUT>10/22/00 09:21a 2,282
BadURLPost.java OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java ... (some output omitted for brevity) OUTPUT>10/12/00 09:29p 151 S
uperFrame.java OUTPUT>10/24/00 09:23p 1,814 TestExec.java OUTPUT>10/09/00 05:47p 23,543
TestStringReplace.java OUTPUT>10/12/00 08:55p 228 TopLevel.java OUTPUT> 22 File(s) 46,661 bytes
OUTPUT> 19,678,420,992 bytes free ExitValue: 0
Copy Code ____________

 

Here the author teaches a very useful method in Windows. Ha-ha, at least I don’t know, that is, cmd.exe/C+, a document name with suffix registered in Windows. Windows will automatically call the relevant program to open this document. I tried it.Next, it’s really good, but it seems that there is a problem if there is a space in the file path, and I can’t solve it by adding quotation marks.

Here the author emphasizes that, instead of assuming that the program you execute is executable, be clear about whether your program is executable alone or interpreted. At the end of this chapter, the author will introduce a command-line tool to help us analyze it.

Another point here is that the way to get the output of process is getInputStream, because from the point of view of Java programs, the output of external programs is input for Java, and vice versa.

The last vulnerability is the mistaken assumption that the exec method will accept all strings you enter and accept on the command line or shell. These errors mainly occur when commands are taken as parameters, and programmers incorrectly add parameter commands that can be entered from all command lines to ex.Ec. In the following example, a programmer wants to redirect the output of a command.

Copy Code ____________
import java.util.*;
import java.io.*;

//StreamGobbler omitted for brevity

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");
Copy Code ____________

 

Running BadWinRedirect produces:

E:classescomjavaworldjpitfallsarticle2>java BadWinRedirect OUTPUT>'Hello World' > test.txt ExitValue: 0

 

The programmer’s intention is to reset the input Hello World to a text file, but the file is not generated. Jecho just outputs the parameters from the command line to the standard output. The user feels that the output can be redirected to a text just like redirection in dos.This is not true. Users mistakenly think of exec as a shell interpreter, but it is not. If you want to redirect the output of one program to another program, you must use the program to implement it. Packages in java.io are available.

Copy Code ____________
import java.util.*;
import java.io.*;

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

public class GoodWinRedirect { 
    public static void main(String args[]) {
        try {  
            FileOutputStream fos = new FileOutputStream(args[0]); 
            Runtime rt = Runtime.getRuntime(); 
            Process proc = rt.exec("java jecho 'Hello World'"); // any
        }
        if (args.length < 1) {
            System.out.println("USAGE java GoodWinRedirect <outputfile></outputfile>"); 
            System.exit(1);
        }
    }
}
Copy Code ____________

 

Running GoodWinRedirect produces:

E:classescomjavaworldjpitfallsarticle2>java GoodWinRedirect test.txt OUTPUT>'Hello World' ExitValue: 0

 

Let’s not say much here, just look at it, and then the author gives a small program for monitoring commands.

Copy Code ____________
import java.util.*; 
import java.io.*;

//class StreamGobbler omitted for brevity

public class TestExec { 
    public static void main(String args[]) { 
        try { 
            String cmd = args[0]; 
            Runtime rt = Runtime.getRuntime(); 
            Process proc = rt.exec(cmd);
            if (args.length < 1) { 
                System.out.println("USAGE: java TestExec "+cmd); 
                System.exit(1); 
            }
        }
    }
}



// any error message? StreamGobbler errorGobbler = new
// StreamGobbler(proc.getErrorStream(), "ERR");

// any output? StreamGobbler outputGobbler = new
// StreamGobbler(proc.getInputStream(), "OUT");

// kick them off errorGobbler.start(); outputGobbler.start();

// any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " +
// exitVal); } catch (Throwable t) { t.printStackTrace(); } } }
Copy Code ____________

 

Run this program:

  E:classescomjavaworldjpitfallsarticle2>java TestExec "e:javadocsindex.html" java.io.IOException: 
CreateProcess: e:javadocsindex.html error=193 at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.<init></init>(Unknown Source) at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source) at TestExec.main(TestExec.java:45)

 

193In Windows, it means that this is not a WIN32 program, which means that the associated program of this page can not be found in the path. Now the author decides to try it with an absolute path.

E:classescomjavaworldjpitfallsarticle2>java TestExec  "e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html" ExitValue: 0

 

That’s good. I tried this one too. It’s IE.

Finally, the author summarizes several rules to prevent us from proceeding.Runtime.exec()An error occurred during the call.

<!—->1、 <!—->You can’t get the exit status of an external process before it’s finished executing

<!—->2、 <!—->When your external program starts to execute, you must immediately control the flow of input, output, and error.

<!—->3、 <!—->You have to use it.Runtime.exec()To execute programs

<!—->4、 <!—->You can’t use it like the command lineRuntime.exec()。

Link of this Article: Use of Java Runtime. exec ()

Leave a Reply

Your email address will not be published. Required fields are marked *