• java动态编译


    一、使用 JavaCompiler 接口来编译 java 源程序(最简单的)

    使用 Java API 来编译 Java 源程式有非常多方法,目前让我们来看一种最简单的方法,通过 JavaCompiler 进行编译。

    我们能通过 ToolProvider 类的静态方法 getSystemJavaCompiler 来得到一个 JavaCompiler 接 口的实例。


    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();


    JavaCompiler 中最核心的方法是 run。通过这个方法能编译 java 源程序。这个方法有 3 个固 定参数和 1 个可变参数(可变参数是从 Jave SE5 开始提供的一个新的参数类型,用 type... argu 表 示)。前 3 个参数分别用来为 java 编译器提供参数、得到 Java 编译器的输出信息及接收编译器的 错误信息,后面的可变参数能传入一个或多个 Java 源程式文件。如果 run 编译成功,返回 0。

    int run(InputStream in, OutputStream out, OutputStream err, String... arguments)

    如果前 3 个参数传入的是 null,那么 run 方法将以标准的输入、输出代替,即 System.in、 System.out 和 System.err。如果我们要编译一个 hello.java 文件,并将使用标准输入输出,run 的使用方法如下:

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

    完整代码如下(用的是 eclipse 工具)

    [java] view plaincopy
     
    1. package com.dongtai.demo;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.InputStreamReader;  
    7.   
    8. import javax.tools.JavaCompiler;  
    9. import javax.tools.ToolProvider;  
    10.   
    11. public class DynamicCompileTest {  
    12.     public static void main(String[] args) throws IOException {  
    13.         // 编译程序  
    14.         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();  
    15.         int result = javaCompiler.run(nullnullnull"-d","./temp/","./temp/com/Hello.java");  
    16.         System.out.println( result == 0 ? "恭喜编译成功" : "对不起编译失败");  
    17.           
    18.         // 运行程序  
    19.         Runtime run = Runtime.getRuntime();  
    20.         Process process = run.exec("java -cp ./temp temp/com/Hello");  
    21.         InputStream in = process.getInputStream();  
    22.         BufferedReader reader = new BufferedReader(new InputStreamReader(in));  
    23.         String info  = "";  
    24.         while ((info = reader.readLine()) != null) {  
    25.             System.out.println(info);  
    26.                   
    27.         }  
    28.     }  
    29. }  



    二、使用 StandardJavaFileManager 编译 Java 源程序

    在第一部分我们讨论调用 java 编译器的最容易的方法。这种方法能非常好地工作,但他确不 能更有效地得到我们所需要的信息,如标准的输入、输出信息。而在 Java SE6 中最佳的方法是使 用 StandardJavaFileManager 类。这个类能非常好地控制输入、输出,并且能通过 DiagnosticListener 得到诊断信息,而 DiagnosticCollector 类就是 listener 的实现。

    使用 StandardJavaFileManager 需要两步。首先建立一个 DiagnosticCollector 实例及通过 JavaCompiler 的 getStandardFileManager()方法得到一个 StandardFileManager 对象。最后通过 CompilationTask 中的 call 方法编译源程序

    每个类的具体方法参数可以查看 jase6 API 文档。上面有很详细的解释

    [java] view plaincopy
     
    1. package com.dongtai.demo;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.File;  
    5. import java.io.FileWriter;  
    6. import java.io.IOException;  
    7. import java.io.InputStream;  
    8. import java.io.InputStreamReader;  
    9. import java.util.Arrays;  
    10.   
    11. import javax.tools.JavaCompiler;  
    12. import javax.tools.JavaCompiler.CompilationTask;  
    13. import javax.tools.StandardJavaFileManager;  
    14. import javax.tools.ToolProvider;  
    15.   
    16. public class DynamicCompileTest {  
    17.     public static void main(String[] args) throws IOException{  
    18.         // 1.创建需要动态编译的代码字符串  
    19.         String nr = " "//回车  
    20.         String source = "package temp.com; " + nr +  
    21.                 " public class  Hello{" + nr +   
    22.                     " public static void main (String[] args){" + nr +   
    23.                         " System.out.println("HelloWorld! 1");" + nr +  
    24.                     " }" + nr +  
    25.                 " }";  
    26.         // 2.将欲动态编译的代码写入文件中 1.创建临时目录 2.写入临时文件目录  
    27.         File dir = new File(System.getProperty("user.dir") + "/temp"); //临时目录  
    28.         // 如果  emp 不存在 就创建  
    29.         if (!dir.exists()) {  
    30.             dir.mkdir();  
    31.         }  
    32.         FileWriter writer = new FileWriter(new File(dir,"Hello.java"));  
    33.         writer.write(source);  
    34.         writer.flush();  
    35.         writer.close();  
    36.           
    37.         // 3.取得当前系统的编译器  
    38.         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();  
    39.         // 4.获取一个文件管理器  
    40.         StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(nullnullnull);  
    41.         // 5.文件管理器根与文件连接起来  
    42.         Iterable it = javaFileManager.getJavaFileObjects(new File(dir,"Hello.java"));  
    43.         // 6.创建编译任务  
    44.         CompilationTask task = javaCompiler.getTask(null, javaFileManager, null, Arrays.asList("-d""./temp"), null, it);  
    45.         // 7.执行编译  
    46.         task.call();  
    47.         javaFileManager.close();  
    48.           
    49.         // 8.运行程序  
    50.         Runtime run = Runtime.getRuntime();  
    51.         Process process = run.exec("java -cp ./temp temp/com/Hello");  
    52.         InputStream in = process.getInputStream();  
    53.         BufferedReader reader = new BufferedReader(new InputStreamReader(in));  
    54.         String info  = "";  
    55.         while ((info = reader.readLine()) != null) {  
    56.             System.out.println(info);  
    57.               
    58.         }  
    59.     }  
    60. }  



    三、从内存中动态编译 java 程序

    JavaCompiler 不仅能编译硬盘上的 Java 文件,而且还能编译内存中的 Java 代码,然后使 
    用 reflection 来运行他们。我们能编写一个类,通过这个类能输入 Java 原始码。一但建立这个对
    象,你能向其中输入任意的 Java 代码,然后编译和运行。

    [java] view plaincopy
     
      1. package com.dongtai.demo;  
      2. import java.io.BufferedReader;  
      3. import java.io.File;  
      4. import java.io.FileWriter;  
      5. import java.io.IOException;  
      6. import java.io.InputStream;  
      7. import java.io.InputStreamReader;  
      8. import java.io.PrintWriter;  
      9. import java.io.StringWriter;  
      10. import java.lang.reflect.InvocationTargetException;  
      11. import java.lang.reflect.Method;  
      12. import java.net.URI;  
      13. import java.net.URL;  
      14. import java.net.URLClassLoader;  
      15. import java.util.Arrays;  
      16.   
      17. import javax.tools.JavaCompiler;  
      18. import javax.tools.JavaCompiler.CompilationTask;  
      19. import javax.tools.JavaFileObject;  
      20. import javax.tools.StandardJavaFileManager;  
      21. import javax.tools.ToolProvider;  
      22.   
      23. public class DynamicCompileTest {  
      24.     public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{  
      25.           
      26.         /* 
      27.          * 编译内存中的java代码 
      28.          * */  
      29.         // 1.将代码写入内存中  
      30.         StringWriter writer = new StringWriter(); // 内存字符串输出流  
      31.         PrintWriter out = new PrintWriter(writer);  
      32.         out.println("package com.dongtai.hello;");  
      33.         out.println("public class Hello{");  
      34.         out.println("public static void main(String[] args){");  
      35.         out.println("System.out.println("HelloWorld! 2");");  
      36.         out.println("}");  
      37.         out.println("}");  
      38.         out.flush();  
      39.         out.close();  
      40.           
      41.         // 2.开始编译  
      42.         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();  
      43.         JavaFileObject fileObject = new JavaStringObject("Hello", writer.toString());  
      44.         CompilationTask task = javaCompiler.getTask(nullnullnull, Arrays.asList("-d","./bin"), null, Arrays.asList(fileObject));  
      45.         boolean success = task.call();  
      46.         if (!success) {  
      47.             System.out.println("编译失败");  
      48.         }else{  
      49.             System.out.println("编译成功");  
      50.         }  
      51.         URL[] urls = new URL[]{new URL("file:/" + "./bin/")};  
      52.         URLClassLoader classLoader = new URLClassLoader(urls);  
      53.         Class classl = classLoader.loadClass("com.dongtai.hello.Hello");  
      54.         Method method = classl.getDeclaredMethod("main", String[].class);  
      55.         String[] argsl = {null};  
      56.         method.invoke(classl.newInstance(), argsl);  
      57.       
      58.     }  
      59. }  
  • 相关阅读:
    HDFS源码分析(六)-----租约
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(一)-----ApplicationMaster
    YARN源码分析(二)-----ResourceManager中的NM节点管理
    YARN源码分析(二)-----ResourceManager中的NM节点管理
    Confluence 6 如何备份和恢复
    Confluence 6 那些文件需要备份
    Confluence 6 确定一个生产系统备份方案
    Confluence 6 生产环境备份策略
  • 原文地址:https://www.cnblogs.com/sunwubin/p/3545840.html
Copyright © 2020-2023  润新知