Let's start with the runtime class, which is a class related to the JVM run-time environment, which is singleton. I say a few places that I think are important.
1. Runtime.getruntime () can get the runtime environment of the current JVM, which is the only way to get a run-time environment in Java.
2. Most of the other methods on runtime are instance methods, which means that the GetRuntime method is used every time a run-time call is made.
3. The exit method in runtime is the way to exit the current JVM and is estimated to be the only one, because I see that exit in the system class actually exits the JVM by calling Runtime.exit (). Here is a description of the Java runtime return value of the general rules (also mentioned below), 0 for normal exit, not 0 for abnormal abort, this is only the Java rules, in each operating system will always occur some small confusion.
4, Runtime.addshutdownhook () method can register a hook when the JVM executes the shutdown, the parameter of the method can be as long as it is an initialized thread instance that is not executed. (Note that the thread in Java is executed and worthless.)
5, speaking of Addshutdownhook this method is to say how the JVM operating environment under what circumstances shutdown or abort. This is written on the document, when the last sprite process exits or receives a user interrupt signal, the user logout, the system shutdown, the runtime exit method is invoked, the JVM initiates the shutdown process, and after this process begins, He will launch all registered shutdown hooks in parallel (note that it is started in parallel, which requires thread safety and prevents deadlocks). When the shutdown process is started, only the halt method can be invoked to abort the shutdown process and exit the JVM.
So when will the JVM abort out? First of all, the JVM just stops running when abort exits, but does not necessarily shutdown. This can occur only if the JVM encounters an internal error such as a sigkill signal or a signal that Windows aborts a process, and a local method that occurs similar to accessing an illegal address. In this case, there is no guarantee that the shutdown hook is executed.
Now start reading this article, hehe.
First, all overloads of the Runtime.exec () method are spoken. One thing to note here is the public Process exec (string [] Cmdarray, String [] envp); In this method Cmdarray is a string array of commands and arguments executed. The first element of the array is the command to be executed, followed by the parameters of the command, envp my personal feeling should be the same as the environment variables in the EXECVE in C, envp in the Name=value way.
1, a very bad calling program, the code is as follows, the program called an external command with exec immediately after the use of Exitvalue to check its return value, let us see what will happen.
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 ();
}
}
}
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)
Here to see the original text can be understood, the main problem here is the wrong call Exitvalue to get the return value of the external command (oh, this error I have made), because Exitvalue this method is not blocked, When the program calls this method, the external command does not return so that it causes an exception, and here is another way to wait for the external command to complete, the WAITFOR method, which blocks until the execution of the external command is completed, and then returns the result of the external command execution. The author here A criticism of the designer's thinking there is a problem, hehe, anyway, I do not matter ah, can be used to pull. But the author here has a note that Exitvalue is also a lot of uses. Because when you raise the WAITFOR method on a process, the current thread is blocked, and if the external command cannot be completed, your thread will remain blocked and the accident will affect the execution of our program. So when we can't tell when an external command has been executed and our program still needs to be executed, we should loop through the Exitvalue to get the return status of the external command and make the corresponding processing when the external command returns.
2, to the Exitvalue department improved procedures
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 ();
}
}
}
Unfortunately, this program is also unable to perform, it has no output but has been hanging there, this is why that.
This is explained in the JDK documentation: because the local system is valid for the buffer pool provided by the standard input and output, the error of fast writing to the standard output and fast reading from the standard input can cause the lock of the child process, even deadlock.
When the document was quoted, the author began to criticize it, saying that the JDK simply explained why the problem happened, but it did not explain how the problem was solved, which was a real problem. The author then says that after executing the external command we have to control all the inputs and outputs of the process (as the case may be), in this case because the call is Javac, and he will output the hint information to the standard error without parameters. So we're going to deal with this in the following procedure.
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 ();
}
}
}
The running result of the program is
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 Fil Es
-nowarn Generate No warnings
-verbose output messages about what the compiler is doing
-deprecation Output sou RCE 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 ;d irs></dirs>override location of installed extensions
-D <directory></directory>specify Where to, generated class files
-encoding <encoding></encoding>specify character encoding used by Sou Rce Files
-target <release></release>generate class files for specific VM version
Process Exitvalue:2
Well, anyway, it came out. The author makes a summary, that is, in order to handle the large output of the external command, you have to make sure that your program handles the input or output required by the external command.
Next topic, when we call an error that is easy to happen when we think it is executable (I just made this mistake tonight, nothing happened when I did this exercise)
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 ();
}
}
}
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)
To be honest, this mistake is really confusing me, I think the return of 2 in Windows should not be found in this file, may be only the cmd command in Windows 2000, dir command is not the current environment variable can explain it. I don't know, look down slowly.
Hey, that's exactly what the author thought, because the dir command was interpreted by the interpreter in Windows, and the Dir.exe command was not found when executing dir directly, so the file could not find the 2 error. If we want to execute such a command, we must first perform different interpreter Command.com or Cmd.exe according to the different operating system.
The above procedure was modified by the author
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 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 ();
}
}
}
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 Superframe.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> File (s) 46,661 bytes
output> 19,678,420,992 bytes Free
exitvalue:0
Here the author teaches a very useful method in Windows, hehe, at least I do not know, is cmd.exe/c + a file name registered suffix in Windows, Windows will automatically invoke the relevant program to open the document, I tried it, really good, But as if there were spaces in the file path, there was a problem, and I couldn't fix it with quotes.
Instead of assuming that the program you are executing is an executable program, and that you know whether your program is executable alone or interpreted, the end author of this chapter introduces a command-line tool to help us analyze it.
The point here is that the output of the process is getinputstream, because from the point of view of the Java program, the output of the external program is input to Java, and vice versa.
The final flaw is that the Exec method accepts all the strings you enter and accept in the command line or shell. These errors are mainly in the case of a command as a parameter, the programmer mistakenly adds all the command line parameters that can be entered in exec (this translation is not good enough to see). The following example is the output of a programmer who wants to redirect a command.
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");
Kick them off
Errorgobbler.start ();
Outputgobbler.start ();
Any error???
int exitval = Proc.waitfor ();
System.out.println ("Exitvalue:" + exitval);
catch (Throwable t)
{
T.printstacktrace ();
}
}
}
Running Badwinredirect produces:
E:classescomjavaworldjpitfallsarticle2>java Badwinredirect
Output> ' Hello World ' > Test.txt
exitvalue:0
The programmer's intention was to redirect the input of Hello world into a text file, but this file was not generated, Jecho just output the parameters in the command line to the standard output, and the user felt that the output could be redirected to a file like a DOS redirect, but that was not possible. The user mistakenly sees exec as a shell interpreter, but it is not, and if you want to redirect the output of a program to another program, you must use the program to implement it. The packages in Java.io are available.
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[])
{
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 ();
}
}
}
Running Goodwinredirect produces:
E:classescomjavaworldjpitfallsarticle2>java Goodwinredirect Test.txt
Output> ' Hello World '
exitvalue:0
There is no more to say, look at it, and then the author gives a small program to monitor the command
Import java.util.*;
Import java.io.*;
Class Streamgobbler omitted for brevity
public class Testexec
{
public static void Main (String args[])
{
if (Args.length < 1)
{
System.out.println ("Usage:java testexec" "cmd");
System.exit (1);
}
Try
{
String cmd = args[0];
Runtime RT = Runtime.getruntime ();
Process proc = rt.exec (cmd);
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 ();
}
}
}
To 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)
193 in Windows is said this is not a Win32 program, which indicates that the path can not find the Web page of the Association program, the following author decided to use an absolute path to try.
E:classescomjavaworldjpitfallsarticle2>java testexec
"E:program Filesnetscapeprogramnetscape.exe e:javadocsindex.html"
exitvalue:0
Easy to use, this I also tried a bit, with IE.
Finally, the author sums up a few rules to prevent us from having an error while making a runtime.exec () call.
1. You can't get his exit status until an external process finishes executing.
2. You must immediately control the input, output, and error flow when your external program starts to execute.
3, you must use Runtime.exec () to carry out the program
4, you cannot use Runtime.exec () as the command line.