动态编译Java源文件(code)

http://www.infoq.com/cn/articles/cf-java-byte-code


import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;


public class Main {

    public static void main(String[] args) {
        String className = "Test";
        String methodName = "test";
        String source = "public class " + className +
            " { public static void " + methodName +
            " () {System.out.println("Hello World!");} }";
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics =
            new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager fileManager =
            compiler.getStandardFileManager(null, null, null);
        StringSourceJavaObject sourceObject = null;
        try {
            sourceObject = new StringSourceJavaObject(className, source);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(sourceObject);
        String path = System.getProperty("user.dir") + File.separator + "bin";
        // 编译选项,将编译产生的类文件放在bin/目录下, see "javac -help"
        Iterable<String> options = Arrays.asList("-d", path, "-cp", path);
        CompilationTask task = compiler.getTask(
                null, fileManager, diagnostics, options, null, fileObjects);
        boolean result = task.call();
        if (!result) {
           System.out.println("编译失败");
           return;
        }
        
        try {
            ClassLoader loader = Main.class.getClassLoader();
//            ClassLoader loader = fileManager.getClassLoader(null);
            Class<?> c = loader.loadClass(className);
            Method m = c.getMethod(methodName, new Class[]{});
            m.invoke(c, null);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    
    static class StringSourceJavaObject extends SimpleJavaFileObject {

        private String content = null;
        public StringSourceJavaObject(String name, String content) throws URISyntaxException {
           super(URI.create("string:///" + name.replace(‘.’,’/‘) + Kind.SOURCE.extension), Kind.SOURCE);
           this.content = content;
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
           return content;
        }
     }

}