zoukankan      html  css  js  c++  java
  • java笔记十一:动态编译

      JDK6.0推出了动态编译的新功能,能够在程序中动态的写一个类,再对之进行编译。编译成class文件后就可以通过类加载方式把动态编译的类加载到内存中。当然也能通过RunTime类调用javac命令来动态编译。

      动态编译类的主要步骤:

      ①、写一个字符串,这个字符串就是要编译的类的全部内容。

      ②、通过输出流,把该字符串的内容写到工程下面指定的包中。

      ③、对创建的java文件进行编译。

        动态编译涉及的类有JavaCompiler、StandardJavaFileManager,具体如何编译看下面的例子。

      ④、把编译后的字节码加载到内存,然后对其进行操作。

     1 package com.compiler;
     2 import java.io.*;
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.net.URI;
     5 import java.net.URL;
     6 import java.net.URLClassLoader;
     7 import java.util.Arrays;
     8 
     9 import javax.tools.JavaCompiler;
    10 import javax.tools.SimpleJavaFileObject;
    11 import javax.tools.StandardJavaFileManager;
    12 import javax.tools.JavaFileObject; 
    13 import javax.tools.ToolProvider;
    14 
    15 public class CompilerAPITester {
    16     private static String JAVA_SOURCE_FILE = "DynamicObject.java";
    17     private static String JAVA_CLASS_FILE = "DynamicObject.class";
    18     private static String JAVA_CLASS_NAME = "DynamicObject";
    19 
    20     public static void main(String[] args) throws IOException, InterruptedException {
    21         //创建java文件
    22         String tr = "\r\n";
    23         String source = "package com.compiler;" + tr +
    24                 "public class "+JAVA_CLASS_NAME+ "{ " + tr +
    25                 "    public static void main(String[] args) {" + tr +
    26                 "        System.out.println(\"Hello World!\");" + tr +
    27                 "    } " + tr +
    28                 "}";
    29         String fileName = System.getProperty("user.dir")+"\\src\\com\\compiler\\"+JAVA_SOURCE_FILE;
    30         FileWriter fw = new FileWriter(fileName); //字符输出流
    31         PrintWriter pw = new PrintWriter(fw);     //将字节输出流转为PrintWriter
    32         pw.write(source);
    33         pw.close();
    34         //编译java文件
    35         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    36         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    37         Iterable sourcefiles = fileManager.getJavaFileObjects(fileName);
    38         //指定编译文件存放位置,如果不指定的话,编译的文件会和java源文件在一个文件夹中
    39          //这样的话加载类的时候会报java.lang.ClassNotFoundException
    40         Iterable<String> options = Arrays.asList("-d", System.getProperty("user.dir")+"\\WebRoot\\WEB-INF\\classes");
    41         compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();
    42         fileManager.close();
    43         //方法二:
    44         /*Runtime runtime = Runtime.getRuntime();
    45         runtime.exec("javac -d "+ System.getProperty("user.dir")+"\\WebRoot\\WEB-INF\\classes " +fileName);
    46         Thread.sleep(1000);*/ //因为这种方法时调用一个线程取编译,所以要让主线程睡一会儿,否则还没编译完主线程就加载类了,会导致报类无法找到的异常
    47         try {
    48             //加载类到内存
    49             //方法一:
    50             //Class c = Class.forName("com.compiler."+JAVA_CLASS_NAME);
    51             //方法二:
    52             //Class c = ClassLoader.getSystemClassLoader().loadClass("com.compiler."+JAVA_CLASS_NAME);
    53             //方法三:
    54             URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src")};
    55             URLClassLoader loader = new URLClassLoader(urls);
    56             Class c = loader.loadClass("com.compiler."+JAVA_CLASS_NAME);
    57             //调用加载类的main方法
    58             c.getMethod("main",String[].class).invoke(null, (Object)new String[]{"a"});
    59         } catch (Exception e) {
    60             // TODO Auto-generated catch block
    61             e.printStackTrace();
    62         }
    63     }
    64 
    65 } 
  • 相关阅读:
    Servlet 生命周期、工作原理(转)
    JVM的内存区域划分(转)
    Java的四个基本特性和对多态的理解
    单例模式和多例模式的区别(转)
    TCP/IP协议体系结构简介
    数据库优化性能
    存储过程的优缺点(转)
    ConurrentHashMap和Hashtable的区别
    XML和JSON优缺点
    HashMap和HashTable的区别
  • 原文地址:https://www.cnblogs.com/liuling/p/dynamicCompiler.html
Copyright © 2011-2022 走看看