In Sun JDK 1.2 and subsequent versions, a set of APIs that can be compiled and executed in the program running time, and execute Java code. These APIs are included in the Tools.jar class library. This feature allows the Java program to dynamically compile, execute small code blocks during runtime, in some cases, in some cases, will make the Java application architecture more flexible and open.
This article assumes that the reader has installed and configured the Sun JDK 1.2 or higher in the computer, and understanding the Javac compiler command.
Using compilers in Java programs
Assume that you want to use the Javac command to compile the Test.java file, and set the class file to save under the / home / mytest / classes path, enter the following command:
Javac -d / home / mytest / classes test.java
The same purpose can also be implemented using the API of a Java compiler provided by Sun. Its use is also very simple, the core code segment is as follows:
...
String [] args = new string [] {"-d", "/ home / mytest / classes", "test.java"};
Int status = javac.compile (args);
...
The Javac Compilation Tool is installed in the / bin directory of the JDK root directory, which is responsible for compiling the source code into the bytecode running on the JVM. In fact, we often use the Javac compilation tool under the / bin directory to compile the Java source file. If you dynamically build an arbitrary-established Java statement in a Java program, use this external Javac compiler is not flexible enough. Although it is sometimes possible to perform an external command using the runtime class, if you want to know if the code is compiled, what happens when compiling, it is difficult to implement the exec () method of the Runtime class.
In Sun's JDK 1.2 and subsequent versions, the JDK installation path contains a Tools.jar file, which contains a complete compiler package. com.sun.tools.javac.main is the main entry of the compiler. If you are familiar with the method of use of the Javac compiler command line, it is easy to understand how this class is used. Method Compile (String [] P) Perform compilation action, parameter P is a string array that stores the parameter option for the javac command, and the compiled state returns an int value, and the corresponding value reference is as follows:
Table status parameter and corresponding value
EXIT_OK 0
EXIT_ERROR 1
EXIT_CMDERR 2
EXIT_SYSERR 3
EXIT_ABNORMAL 4
Compile and execute the Java statement when executed
From the above, we have basically learned how to dynamically build a Java file. So, how do I run when I run dynamic compile the specified Java statement? A trick is required here.
The Java balance sentence to be dynamically compiled is as follows:
System.out.println ("Hello, this runtime code!");
The compiler does not support compiling a single Java statement, the compiled object must be a .java as a sub-source program file, so it is necessary to transform this statement, become a complete class, and put this The statement is placed in the main method for easy testing.
Public Class
Public static void main (string [] args) throws exception {
System.out.println ("Hello, this runtime code!");
}
}
In this way, the code that is dynamically compiled has been dynamically assembled into the code above, and the preparation has not yet ended, but it seems to work slightly complicated. Because the above code is currently stored in memory, the compiler seems to be more interested in a hard disk file. We need to reference the Java.IO.File class (JDK 1.2 or more), create a temporary file to store the contents of the above code. The static method of the java.io.file class CreateTempFile () method guarantees that the file name created is not repetitive, which increases the flexibility of this program. Flexibility depends on the policy that is really applied to the system architecture. System.getProperty ("user.dir") is used to get the current path, here as the storage directory of the temporary file.
File file;
File = file.createTempfile ("Javaruntime", ".java", New file (System.GetProperty ("User.dir"))));
String filename = file.getname ();
String classname = getclassname (filename);
// output the code to the file
PrintWriter out = new printwriter (new fileoutputstream (file);
Out.println ("Public Class" ClassName "{"};
Out.println (".. Code ..");
OUT.PRINTLN ("}");
// Turn the file stream
Out.flush ();
Out.close ();
We agree that the temporary file name created with "javaruntime" is your head (can be named), the suffix name ends with ".java". A Java source file to be compiled has been dynamically generated. Next step to create a main instance from a com.sun.tools.javac package, call the javac.compile () method to compile this temporary file:
Private static com.sun.tools.javac.main javac = new com.sun.tools.javac.main ();
String [] args = new string [] {"-d", system.getproperty ("user.dir"), filename};
Int status = javac.compile (args);
Assuming that the temporary file passed the verification of the compiler text method, the compile success (the status value is equal to 0, see the front table), and a Java class file will be more than a Java class file in the current program. We will simulate the result of dynamically compiling code by executing this Java class file.
Java provides features that load classs at runtime, dynamically identify and call class constructors, class fields, and class methods. Java.Lang.Reflect.Method implements the Member interface, you can call the interface method to get the name, modifying words, etc. of the method class. Method Gtruturntype (), getParameterTypes (), getExeptionTypess (), etc. Returns constructor of the representation. Another important feature of Method is to call the invoke () to perform this method (detailed usage) can be viewed. In the following code, create a java.lang.reflect.Method class method, call the getMethod () method to get the mapping of the Main method being assembled, this code is as follows:
Try {
// Access this class
Class CLS = Class.Forname (classname);
// Call the main method
Method main = CLS.GETMETHOD ("main", new class [] {string []. Class};
Main.invoke (null, new object [] {new string [0]});
} catch (securityException se) {
Debug ("Access to the Information is Denied:" Se.toString ());
} catch (nosuchmethodexception nme) {
Debug ("A Matching Method Is Not Found or if Then Name IS OR:
Nme.tostring ());
} catch (invocationTargeTexception ITE) {
Debug ("Exception In Main:" ITE.GETTARGETEXCEPTION ());
} catch (exception e) {
DEBUG (E.toTString ());
}
For example, the operation results are as follows:
Hello, this runtime code!
Demo procedure
A simple Java program is given below, which shows how to complete the dynamic compile of Java statements using Sun's Javac compiler. Running the program requires a computer to install JDK 1.2 or higher, and specify the Tools.jar file location in ClassPath or when running.
Program structure:
◆ Compile () compile Java code, return to the generated temporary file;
◆ Run () runs the compiled class file;
◆ DEBUG () output debugging information;
◆ getClassName () get the name from a Java source file;
◆ Readline () reads the Java Code input from the console.
Import java.io.file;
...
Public class runtimecode {
/**translater*/
Private static com.sun.tools.javac.main javac = new com.sun.tools.javac.main ();
/ ** Wait for the user to enter JavaCode, then compile, execute * /
Public static void main (string [] args) throws exception {
...
Run (Compile (CODE));
}
/ ** Compile JavaCode, return to temporary file object * /
Private synchronized static file compile (String code)
THROWS IOEXCEPTION, EXCEPTION {
File file;
// Create a temporary code file in the user's current file directory
File = file.createTempfile ("Javaruntime", ".java",
New file (System.getProperty ("User.Dir"))))));
// Remove this temporary Java source file when the virtual machine exits
File.deleteOnd ();
// Get file names and class names
String filename = file.getname ();
String classname = getclassname (filename);
// output the code to the file
PrintWriter out = new printwriter (new fileoutputstream (file);
OUT.PRINTLN ("/ **");
...
// Turn the file stream
Out.flush ();
Out.close ();
// Compile code file
String [] args = new string [] {"-d", system.getproperty ("user.dir"), filename}; // Returns the compiled status code
Int status = javac.compile (args);
// Process the compilation status
...
}
/ ** Execute a class file that has just been compiled * /
Private static synchronized void run (file file)
...
// Delete this temporary compiled class file when the virtual machine exits
New file (file.getparent (), classname ".class"). deleteOnExit ();
Try {
// Access this class
Class CLS = Class.Forname (classname);
// Map MAIN method
Method main = CLS.GETMETHOD ("main", new class [] {string []. Class};
// Execute the main method
Main.invoke (null, new object [] {new string [0]});
} catch (securityException se) {
...
}
}
/ ** Print debugging information * /
Private static void debug (string msg) {
System.err.Println (MSG);
}
/ ** Get class names based on a Java source file name * /
Private static string getclassname (String filename) {
Return filename.substring (0, filename.length () - 5);
}
/ ** Java code segment input from the user from the console * /
...
}
Compile the above code, enter the following code at the Please Input Java Code:
For (int i = 0; i <10; i ) {system.out.println ("this is:" i);}
The results are as follows:
Please Input Java Code:
For (int i = 0; i <10; i ) {system.out.println ("this is:" i);}
Wait ....
--------------------
THIS is: 0
THIS IS: 1
THIS IS: 2
THIS IS: 3
THIS IS: 4
THIS IS: 5
THIS IS: 6
THIS IS: 7
THIS IS: 8
THIS IS: 9
to sum up
In large and medium-sized enterprise applications, use code dynamic compilation technology to combine OO programming models to ensure system scalability and scalability under system-free conditions. If you are a Java programmer, you can add the above code, you can also help debug a small segment of Java code.