Java 内存级动态编译

来源:互联网 发布:淘宝怎样设置自动回复 编辑:程序博客网 时间:2024/06/07 20:14

先定义接口:

package Test;public interface Printer {public void print();}

然后如下:

package Test;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.URI;import java.util.Arrays;import javax.tools.FileObject;import javax.tools.ForwardingJavaFileManager;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import javax.tools.JavaFileManager;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import javax.tools.JavaFileObject.Kind;import javax.tools.ToolProvider;public class MyTest {//自定义JavaSourceFromString,作为源代码的抽象文件static class JavaSourceFromString extends SimpleJavaFileObject{final String code ;public JavaSourceFromString(String name,String code) {super(URI.create("string:///"+name.replace('.', '/')+Kind.SOURCE.extension), Kind.SOURCE);this.code = code;}@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors){return code ;}}//JavaClassFileObject,代表class的文件抽象static class JavaClassFileObject extends SimpleJavaFileObject{ByteArrayOutputStream outputStream=null;public JavaClassFileObject(String className, Kind kind) {super(URI.create("string:///"+className.replace('.', '/')+kind.extension), kind);outputStream = new ByteArrayOutputStream();}@Overridepublic OutputStream openOutputStream() throws IOException{return this.outputStream;}public byte[] getClassBytes(){return outputStream.toByteArray();}}//ClassFileManager,修改JavaFileManager生成class的JavaFileObject的行为,另外返回一个自定义ClassLoader用于返回内存中的字节码对应的类模板static class ClassFileManager extends ForwardingJavaFileManager<JavaFileManager>{private JavaClassFileObject classFileObject;protected ClassFileManager(JavaFileManager fileManager) {super(fileManager);}@Overridepublic JavaFileObject getJavaFileForOutput(Location location,String className,Kind kind,FileObject sibling) throws IOException{classFileObject = new JavaClassFileObject(className, kind);return classFileObject;}@Overridepublic ClassLoader getClassLoader(Location location){return new ClassLoader() {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException{byte[] classBytes = classFileObject.getClassBytes();return super.defineClass(name, classBytes, 0, classBytes.length);}};}}public static void main(String[] args) {String string = "package Test; \n" + "public class MyPrint implements Printer{ \n" + "@Override \n"+ "public void print() { \n" + "System.out.println(\"MyPrint...\"); \n" + "} \n" + "}";//生成源代码的JavaFileObjectSimpleJavaFileObject fileObject = new JavaSourceFromString("Test.MyPrint", string);JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//被修改后的JavaFileManagerJavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null));//执行编译CompilationTask task = compiler.getTask(null, fileManager, null, null, null, Arrays.asList(fileObject));task.call();//获得ClassLoader,加载class文件ClassLoader classLoader = fileManager.getClassLoader(null);try {Class<?> printClass = classLoader.loadClass("Test.MyPrint");//获得实例Printer printer = (Printer)printClass.newInstance();printer.print();} catch (Exception e) {e.printStackTrace();}}}