[Reseller Note] For many application systems, dynamic loading and execution classes and code snippets are often required, which facilitates deployment simplicity and system design flexibility. This article provides a comprehensive introduction, which is worth your reference.
In Sun JDK 1.2 and later versions, it contains a group of APIs that can compile and execute Java code at runtime. These APIs are included in the tools. Jar class library. This function allows Java programs to dynamically compile and execute Small code blocks during runtime. In some cases, this function makes the Java application architecture more flexible and open.
This article assumes that the reader has installed and configured Sun JDK 1.2 or later on the computer, and has some knowledge about javac compiler commands.
Use a compiler in a Java program
Suppose you want to use the javac command to compile the test. Java file in the/home/mytest directory, and set the class file to be stored in the/home/mytest/classes path. Enter the following command:
Javac-D/home/mytest/classes test. Java
To achieve the same purpose, you can also use a Java compiler API provided by Sun. It is also easy to use. The core code segment is as follows:
- ...
- String[] ARGs =New String[] {"-D", "/homemytestclasses", "test. Java "};
- Int status = javac. Compile (ARGs );
- ...
The javac compilation tool is installed in the/bin directory of the JDK root directory and is responsible for compiling the source code into the bytecode running on JVM. In fact, we often use the javac compilation tool in the/bin directory to compile Java source files. If you dynamically compile arbitrary Java statements in a Java program, the use of this external javac compiler is not flexible enough. Although you can use the runtime class to execute an external command, if you want to know whether the code is compiled and what error occurs during compilation, use the exec () the method is very difficult to implement.
In Sun's JDK 1.2 and later versions, the/lib path of the JDK installation path contains a tool. jar file, which contains a complete compiler package. Com. Sun. Tools. javac. Main is the main class entry of the compiler. If you are familiar with the use of the javac compiler command line, it is easy to understand how to use this class. The compile (string [] P) method executes the compilation action. The parameter P is a string array used to store the Parameter options of the javac command. An int value is returned for the compiled status, the corresponding values are shown in the following table:
Table status parameters and corresponding values
Exit_ OK 0
Exit_error 1
Exit_cmderr 2
Exit_syserr 3
Exit_abnormal 4
Compile and execute Java statements during Program Execution
From the above section, we have basically learned how to dynamically compile a Java file. So how to dynamically compile the specified Java statement during runtime? Here is a tip.
Assume that the Java statements to be dynamically compiled are as follows:
- System. Out. println ("hello, this runtime code !");
The compiler does not support compiling a single Java statement. The compiled object must be. java is a suffix and has a valid structure class source program file. Therefore, you need to transform this statement into a complete class and put this statement into the main method for testing.
- Public Class<Temporary class file name> {
- Public Static VoidMain (String[] ARGs)Throws Exception{
- System. Out. println ("hello, this runtime code !");
- }
- }
In this way, the code to be dynamically compiled has been dynamically assembled into the above Code by the program. The preparation work is not over yet, but it seems that the work tends to be slightly complicated. Because the above Code is still stored in the memory, the compiler seems more interested in a hard disk file. We need to reference the java. Io. File class (JDK 1.2 or above) and create a temporary file to store the content of the above Code. The static method createtempfile () of the Java. Io. File class ensures that the created file names are non-duplicated, which increases the flexibility of this program. Flexibility depends on the policies applied to the system architecture.
System. getproperty ("user. dir") is used to obtain the current path, which serves as the directory for storing temporary files.
- File file;
- File = file. createtempfile ("javaruntime", ". Java ",NewFile (System. Getproperty ("user. dir ")));
- StringFilename = file. getname ();
- StringClassname = getclassname (filename );
- // Output code to a file
- Printwriter out =NewPrintwriter (NewFileoutputstream (File ));
- Out. println ("Public Class"+ Classname +" {"};
- Out. println ("... code ..");
- Out. println ("}");
- // Close the file stream
- Out. Flush ();
- Out. Close ();
We agree that the temporary file name to be created will be suffixed with "javaruntime" (which can be any name), and the suffix will end with ". Java. A Java source file to be compiled has been dynamically generated. Next, create a main instance from the com. Sun. Tools. javac package and call the javac. Compile () method to compile the temporary file:
- PrivateStaticCom. Sun. Tools. javac. Main javac =NewCom. Sun. Tools. javac. Main ();
- String[] ARGs =New String[] {"-D ",System. Getproperty ("user. dir"), filename };
- Int status = javac. Compile (ARGs );
Assuming that the temporary file has passed the compiler syntax verification and other verification, the compilation is successful (the value of status is equal to 0, see the previous table), and a Java class file will be added to the running directory of the current program. We will simulate the execution of the Code to be dynamically compiled by executing this Java class file.
Java provides the ability to load classes at runtime, dynamically identifying and calling class constructor methods, class fields, and class methods. Java. Lang. Reflect. method implements the member interface. You can call the interface method to obtain the name and modifier of the method class. Methods such as getruturntype (), getparametertypes (), and getexeptiontypess () return the construction information of the represented method. Another important feature of method is that you can call invoke () to execute this method (for detailed usage, you can view the java. Lang. Reflect package documentation ). The following code creates a java. Lang. Reflect. method class method and calls the getmethod () method to obtain the ing of the assembled main method. The Code is as follows:
- Try{
- // Access this class
- ClassCLS =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(SecurityexceptionSe ){
- Debug ("Access to the information is denied:" + Se. tostring ());
- }Catch(NosuchmethodexceptionNME ){
- Debug ("a matching method is not found orIfThen name is or:
- "+ NME. tostring ());
- }Catch(InvocationtargetexceptionITE ){
- Debug ("ExceptionIn Main: "+ ite. gettargetexception ());
- }Catch(ExceptionE ){
- Debug (E. tostring ());
- }
The running result parameters are as follows:
Hello, This runtime code!
Demonstration procedure
The following is a simple Java program, which explains how to use sun's javac compiler to dynamically compile Java statements. To run this program, you must install JDK 1.2 or later on your computer and specify the location of the tools. jar file in classpath or during running.
Program structure:
◆ Compile () compiles Java code and returns the generated temporary file;
◆ Run () run the compiled class file;
◆ Debug () Outputs debugging information;
◆ Getclassname () obtains the class name from a Java source file;
◆ Readline () reads the Java code entered by the user from the console.
- Import java. Io.File;
- ...
- PublicClassRuntimecode {
- /** Compiler */
- Private StaticCom. Sun. Tools. javac. Main javac =NewCom. Sun. Tools. javac. Main ();
- /** Wait for the user to enter the javacode and then compile and execute the Code */
- Public Static VoidMain (String[] ARGs)Throws Exception{
- ...
- Run (compile (CODE ));
- }
- /** Compile javacode and return the temporary file object */
- Private Synchronized StaticFile compile (StringCode)
- ThrowsIoexception,Exception{
- File file;
- // Create a temporary code file in the user's current file directory
- File = file. createtempfile ("javaruntime", ". Java ",
- NewFile (System. Getproperty ("user. dir ")));
- // Delete this temporary Java source file when the VM exits
- File. deleteonexit ();
- // Get the file name and Class Name
- StringFilename = file. getname ();
- StringClassname = getclassname (filename );
- // Output code to a file
- Printwriter out =NewPrintwriter (NewFileoutputstream (File ));
- Out. println ("/**");
- ...
- // Close the file stream
- Out. Flush ();
- Out. Close ();
- // Compile the code file
- String [] ARGs = new string [] {"-D", system. getproperty ("user. dir"), filename };
- // Return the compiled status code
- Int status = javac. Compile (ARGs );
- // Process the compilation status
- ...
- }
- /** Execute the compiled class file */
- Private Static Synchronized VoidRun (File file)
- ...
- // Delete this temporarily compiled class file when the VM exits
- NewFile (file. getparent (), classname + ".Class"). Deleteonexit ();
- Try{
- // Access this class
- ClassCLS =Class. Forname (classname );
- // Map the main method
- Method main = Cls. getmethod ("Main ",New Class[] {String[].Class});
- // Execute the main method
- Main. Invoke (Null,New Object[] {New String[0]});
- }Catch(SecurityexceptionSe ){
- ...
- }
- }
- /** Print debugging information */
- Private Static VoidDebug (StringMSG ){
- System. Err. println (MSG );
- }
- /** Obtain the class name based on the name of a Java source file */
- Private Static StringGetclassname (StringFilename ){
- ReturnFilename. substring (0, filename.Length()-5 );
- }
- /** Obtain the Java code segment entered by the user from the console */
- ...
- }
Compile and run the above Code. Enter the following code at the prompt of please input Java code:
For (INT I = 0; I <10; I ++) {system. Out. println ("This is:" + I );}
The running result is 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
Summary
On the Application System Platform of large and medium-sized enterprises, the dynamic code compilation technology combined with the OO programming model can ensure the scalability and scalability of the system without the crash of the system. If you are a Java programmer, slightly adjusting the above Code can also help debug small sections of Java code.