java 6以,jdk里提供了一套编译方法类,可以动态编译java source。
下面这个例子是编译字符串形式的source,直接得到编译后的class的字节进行load。
package jp.co.wqf; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.ForwardingJavaFileObject; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject.Kind; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class Compile { public static void main(String[] args) { String source1 = "package jp.co.wqf; " + "public class Test1 { " + "public static void main(String[] args) {" + "System.out.println(\"this is class Test1\");" + "} " + "}"; String source2 = "package jp.co.wqf; " + "public class Test2 { " + "public static void main(String[] args) {" + "System.out.println(\"this is class Test2\");" + "} " + "}"; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //标准文件管理器,如果只使用它的话,编译出的class是文件形式 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); BytesClassJavaFileManager classJavaFileManager = new BytesClassJavaFileManager(fileManager); SimpleJavaFileObject javaFileObject1 = new StringSourceJavaObject("jp.co.wqf.Test1", source1); SimpleJavaFileObject javaFileObject2 = new StringSourceJavaObject("jp.co.wqf.Test2", source2); Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(javaFileObject1,javaFileObject2); CompilationTask task = compiler.getTask(null, classJavaFileManager, null, null, null, fileObjects); boolean result = task.call(); if (result) { BytesClassLoader loader = new BytesClassLoader(); try { String className = "jp.co.wqf.Test2"; Class<?> clazz = loader.loadClass(className,classJavaFileManager.getClassJavaObject(className)); Method method = clazz.getMethod("main", new Class<?>[]{String[].class}); method.invoke(null, new Object[] {new String[]{}}); } 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(); } } } } //字符串形式的source类 class StringSourceJavaObject extends SimpleJavaFileObject{ private String content = null; protected StringSourceJavaObject(String name, String content) { super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); this.content = content; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return content; } } //字节形式的class类 class BytesClassJavaObject extends ForwardingJavaFileObject<JavaFileObject>{ private ByteArrayOutputStream bos; protected BytesClassJavaObject(JavaFileObject fileObject) { super(fileObject); this.bos = new ByteArrayOutputStream(); } @Override public OutputStream openOutputStream() throws IOException { return bos; } public ByteArrayOutputStream getBos() { return bos; } } //class类的管理器 class BytesClassJavaFileManager extends ForwardingJavaFileManager<JavaFileManager>{ private Map<String, BytesClassJavaObject> map= new HashMap<String, BytesClassJavaObject>(); protected BytesClassJavaFileManager(JavaFileManager fileManager) { super(fileManager); } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { JavaFileObject jfo = super.getJavaFileForOutput(location, className, kind, sibling); BytesClassJavaObject classJavaObject = new BytesClassJavaObject(jfo); map.put(className, classJavaObject); return classJavaObject; } public BytesClassJavaObject getClassJavaObject(String className) { return this.map.get(className); } } //用于装载字节的classloader class BytesClassLoader extends ClassLoader{ public Class<?> loadClass(String fullName, BytesClassJavaObject bcjo) { byte[] classData = bcjo.getBos().toByteArray(); return this.defineClass(fullName, classData, 0, classData.length); } }
转载一个通用方法
package org.ironrhino.core.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URI; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.ForwardingJavaFileObject; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class JavaSourceExecutor { public static void execute(String code, String... args) throws Exception { Class<?> clazz = compile(code); Method method = clazz.getMethod("main", new Class[] { String[].class }); if (method.getReturnType() == Void.TYPE) { int mod = method.getModifiers(); if (Modifier.isStatic(mod) && Modifier.isPublic(mod)) method.invoke(null, new Object[] { args }); } } public static Class<?> compile(String code) throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager stdFileManager = compiler .getStandardFileManager(null, null, null); JavaFileManager fileManager = new ForwardingJavaFileManager<StandardJavaFileManager>( stdFileManager) { @Override public JavaFileObject getJavaFileForOutput(Location location, final String className, Kind kind, FileObject sibling) throws IOException { JavaFileObject jfo = super.getJavaFileForOutput(location, className, kind, sibling); return new ForwardingJavaFileObject<JavaFileObject>(jfo) { @Override public OutputStream openOutputStream() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayClassLoader.getInstance().defineClass( className, bos); return bos; } }; } }; code = complete(code); JavaSource source = new JavaSource(extractClassName(code), code); List<JavaFileObject> list = new ArrayList<JavaFileObject>(); list.add(source); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); compiler.getTask(null, fileManager, diagnostics, null, null, list) .call(); fileManager.close(); List<Diagnostic<? extends JavaFileObject>> diagnos = diagnostics .getDiagnostics(); if (diagnos.size() > 0) { StringBuilder sb = new StringBuilder(); for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics .getDiagnostics()) { sb.append("Error ["); sb.append(diagnostic.getMessage(null)); sb.append("] on line "); sb.append(diagnostic.getLineNumber()); sb.append(" in "); sb.append(diagnostic.getSource().toUri()); } throw new RuntimeException(sb.toString()); } return ByteArrayClassLoader.getInstance().loadClass( source.getClassName()); } private static String complete(String code) { String className = extractClassName(code); if (className == null) { className = "C" + System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); sb.append("public class "); sb.append(className); sb.append("{public static void main(String... args){"); sb.append(code); sb.append("}}"); code = sb.toString(); } return code; } private static Pattern PACKAGE = Pattern.compile("package\\s+(\\w+)"); private static Pattern CLASS = Pattern.compile("class\\s+(\\w+)"); private static String extractClassName(String code) { String p = null; String c = null; Matcher m = PACKAGE.matcher(code); if (m.find()) p = m.group(1); Matcher m2 = CLASS.matcher(code); if (m2.find()) c = m2.group(1); if (c == null) return null; else return p == null ? c : p + "." + c; } static class JavaSource extends SimpleJavaFileObject { private String code; private String className; JavaSource(String className, String code) { super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.className = className; this.code = code; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } public String getClassName() { return className; } } static class ByteArrayClassLoader extends ClassLoader { private static ByteArrayClassLoader instance = AccessController .doPrivileged(new PrivilegedAction<ByteArrayClassLoader>() { @Override public ByteArrayClassLoader run() { return new ByteArrayClassLoader(); } }); private Map<String, ByteArrayOutputStream> bytes = new HashMap<String, ByteArrayOutputStream>(); public static ByteArrayClassLoader getInstance() { return instance; } @Override public Class<?> findClass(String name) { byte[] classData = bytes.remove(name).toByteArray(); return defineClass(name, classData, 0, classData.length); } public void defineClass(String name, ByteArrayOutputStream b) { bytes.put(name, b); } } }
相关推荐
通过java的ToolProvider创建JavaCompile,用来执行class源文件 * 4.创建DiagnosticCollector用来执行获取执行失败的错误结果 * 5.添加动态执行的编译环境 options 是个集合,添加内容,字符集,classpath等 * 6....
compile
Design Compile是synopsys的综合软件,它的功能是把RTL级的代码转化为门级网表。资源适合DC的 初学者
javacompile
protobuf 建立proto文件的依赖编译关系
Python-2.7.13-xcompile.patch
主要介绍了Vue 中的compile操作方法,非常不错,具有参考借鉴价值,需要的朋友参考下吧
Compile-CC 编译器源代码
javaCompile.exe是一个Editplus插件。 可以简化java程序运行流程。 直接运行java,不再先编译再运行。 减少无效动作,增加开发效率。
Compile
VC2005 X64 Compile 設定
compile-node-sass,编译sass/scss为css。
在您的项目中使用要在您的应用程序中使用compiletest-rs ,请将以下内容添加到Cargo.toml[ dev-dependencies ]compiletest_rs = " 0.7 " 默认情况下, compiletest-rs应该能够在稳定的,beta的和夜间的锈蚀通道上...
一个编译器原码,能编译原文件,文档了有详细说明-The original code a compiler can compile the original document, the document has a detailed description
compile的时候。 如果你的WEB APP下都用了大量的第三方jar, 其大小 超过了jvm默认的大小(4M)那么就 会产生此错误信息了。 解决方法: 手动设置MaxPermSize大小 改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m ...
win10下vim开发stm32编译数据库文件例子
python-3.2.2-xcompile.patch,python-3.2.2-xcompile.patch其他版本内核也已经上传
数字后端流程一【Design Compile】实例笔记
1.定义一个结构体,利用该结构体定义一个数组stable,用来存放字符串中字符的属性(类型class和值value)。(与实验一同用)2.定义一个整形数组eft,大小与stable数组相同,记录对应单词位置是否有语法错误