Java Dynamic compilation notes

Source: Internet
Author: User

1 Preface

Java's dynamic compilation knowledge is not often encountered in actual development. However, learning java Dynamic compilation helps us understand java at a deeper level. Understand the dynamic proxy mode of jdk so that we can understand and understand other open-source frameworks. Next we will use the dynamic compilation of java. The APIS for java Dynamic compilation are all in the javax. tools Package.

2. Using the JavaCompiler interface to compile a java source program there are many methods to compile a Java source program using Java APIs. Currently, let's look at the simplest method to compile it using JavaCompiler. We can use the static method getSystemJavaCompiler of the ToolProvider class to obtain an instance of the JavaCompiler interface. JavaCompiler compiler = ToolProvider. getSystemJavaCompiler (); the most important method in JavaCompiler is run. This method can be used to compile the java source program. This method has three fixed parameters and one variable parameter (the variable parameter is a new parameter type provided starting from Jave SE5, with type... Argu ). The first three parameters are used to provide parameters for the java compiler, obtain the output information of the Java compiler, and receive the error information of the compiler. The variable parameters can be passed into one or more Java source program files. If run is compiled successfully, 0 is returned.
Int run (InputStream in, OutputStream out, OutputStream err, String... arguments)

If the first three parameters are null, the run method replaces the standard input and output, namely System. in, System. out, And System. err. If we want to compile a hello. java file and use standard input and output, run is used as follows:

Int results = tool. run (null, "Hello. java ");

The complete code is as follows (using the Eclipse tool)

2.1 Eclipse project
2.2 Hello. java first write this java file to demonstrate how to dynamically compile the Hello. java file.
package my.xyz.hello;public class Hello {public static void main(String[] args) {System.out.println("helloworld!");}}

2.3 DynamicCompileTest. java
Package my. xyz. test; import java. io. bufferedReader; import java. io. inputStream; import java. io. inputStreamReader; import javax. tools. javaCompiler; import javax. tools. toolProvider; public class DynamicCompileTest {public static void main (String [] args) throws Exception {// task: Compile Hello under the temp directory. java file JavaCompiler javaCompiler = ToolProvider. getSystemJavaCompiler (); // get the current system compiler int result = javaCompiler. run (nu Ll, null, null, "-d ",". /temp ",". /temp/Hello. java "); // int result = javaCompiler. run (null, "Hello. java "); System. out. println (result = 0? "Congratulations! compilation successful! ":" Sorry for compilation failure "); // run Hello in the program. classsRuntime run = Runtime. getRuntime (); Process process = run.exe c ("java-cp. /temp my. xyz. hello. hello "); InputStream in = process. getInputStream (); BufferedReader reader = new BufferedReader (new InputStreamReader (in); String info = ""; while (info = reader. readLine ())! = Null) {System. out. println (info );}}}
3. Use StandardJavaFileManager to compile the Java source program. In the first part, we will discuss the easiest way to call the java compiler. This method works well, but it cannot get the information we need more effectively, such as standard input and output information. The best method in Java SE6 is to use the StandardJavaFileManager class. This class can control input and output very well, and obtain diagnostic information through DiagnosticListener, while DiagnosticCollector class is the implementation of listener. Two steps are required to use StandardJavaFileManager. First, create a DiagnosticCollector instance and obtain a StandardFileManager object through the getStandardFileManager () method of JavaCompiler. Finally, compile the source program using the call method in CompilationTask. For details about the method parameters of each class, see the jase6 API documentation. It provides detailed explanations. The complete DEMO code is as follows:
3.1 Eclipse project
3.2 DynamicCompileTest. java
Package my. xyz. test; import java. io. file; import java. io. fileWriter; import java. util. arrays; import javax. tools. javaCompiler; import javax. tools. javaCompiler. compilationTask; import javax. tools. standardJavaFileManager; import javax. tools. toolProvider; public class DynamicCompileTest {public static void main (String [] args) throws Exception {// 1. create the code String to be dynamically compiled String nr = "\ r \ n"; // press enter to wrap String source = "package my. Xyz. hello; "+ nr +" public class Hello {"+ nr +" public static void main (String [] args) {"+ nr +" System. out. println (\ "helloworld! \ ");" + Nr + "}" + nr + "}"; // 2. write the pre-dynamically compiled code to the File. 1. Create a temporary directory. 2. Write the temporary File dir = new File (System. getProperty ("user. dir ") +"/temp "); // temporary directory // if the/temp directory does not exist, create the temp directory if (! Dir. exists () {dir. mkdir ();} FileWriter writer = new FileWriter (new File (dir, "Hello. java "); writer. write (source); // write the string to the writer in the file. flush (); writer. close (); // 3: Obtain the java compiler JavaCompiler javaCompiler = ToolProvider of the current system. getSystemJavaCompiler (); // 4: obtain a file manager, StandardJavaFileManageStandardJavaFileManager, javaFileManager = javaCompiler. getStandardFileManager (null, null, null); // 5. the file manager root is connected to the file Iterable it = javaFileManager. getJavaFileObjects (new File (dir, "Hello. java "); // 6. create a compiled task // CompilationTask task = javaCompiler. getTask (null, javaFileManager, null, it); CompilationTask task = javaCompiler. getTask (null, javaFileManager, null, Arrays. asList ("-d ",". /temp "), null, it); // execute the compilation task. call (); javaFileManager. close ();}}
4. dynamically compile the java program from the memory and load and execute JavaCompiler not only to compile the Java files on the hard disk, but also to compile the Java code in the memory, and then run them using reflection. The complete DEMO code is as follows:
4.1 Eclipse project
4.2 JavaStringObject. java
package my.xyz;import java.io.IOException;import java.net.URI;import javax.tools.SimpleJavaFileObject;public class JavaStringObject extends SimpleJavaFileObject {private String code;public JavaStringObject(String name, String code) {//super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);super(URI.create(name+".java"), Kind.SOURCE);this.code = code;}@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {return code;}}

4.3 DynamicCompileTest. java
Package my. xyz. test; import java. io. printWriter; import java. io. stringWriter; import java. lang. reflect. method; import java.net. URL; import java.net. URLClassLoader; import java. util. arrays; import javax. tools. javaCompiler; import javax. tools. javaCompiler. compilationTask; import javax. tools. javaFileObject; import javax. tools. toolProvider; import my. xyz. javaStringObject; public class DynamicCompileTest {public st Atic void main (String [] args) throws Exception {/** compile the java code in the memory * // write the code into the memory StringWriter writer = new StringWriter (); // memory string output stream PrintWriter out = new PrintWriter (writer); out. println ("package my. xyz. hello; "); out. println ("public class Hello {"); out. println ("public static void main (String [] args) {"); out. println ("System. out. println (\ "helloworld! \ ");"); Out. println ("}"); out. println ("}"); out. flush (); out. close (); // start compiling JavaCompiler javaCompiler = ToolProvider. getSystemJavaCompiler (); JavaFileObject fileObject = new JavaStringObject ("Hello", writer. toString (); CompilationTask task = javaCompiler. getTask (null, Arrays. asList ("-d ",". /bin "), null, Arrays. asList (fileObject); boolean success = task. call (); if (! Success) {System. out. println ("Compilation failed! ");} Else {System. out. println (" compiled successfully! "); // Call the main () Method Using Reflection // Class class1 = Class. forName ("com. ynxinhua. hello. hello "); // ClassLoader is automatically used to find the classpath path under the current working directory, that is, under the bin directory // Class class1 = ClassLoader. getSystemClassLoader (). loadClass ("my. xyz. hello. hello "); // you can use URLClassLoader to instantiate a Class file at any location, this facilitates URL [] urls = new URL [] {new URL ("file:/" + ". /bin/")}; URLClassLoader classLoader = new URLClassLoader (urls); Class class1 = classLoader. loadClass ("my. xyz. hello. hello "); Method method = class1.getDeclaredMethod (" main ", String []. class); String [] args1 = {null}; method. invoke (class1.newInstance (), args1 );}}}




 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.