java内存动态编译执行,java动态编译,一般的java的动态编译
分享于 点击 34287 次 点评:274
java内存动态编译执行,java动态编译,一般的java的动态编译
一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。本例程则不需要生成任何文件,一切在内存中进行。
[Java]代码
package cn.outofmemory.dynamic;public class DynaCompTest { public static void main(String[] args) throws Exception { String fullName = "DynaClass"; StringBuilder src = new StringBuilder(); src.append("public class DynaClass {\n"); src.append(" public String toString() {\n"); src.append(" return \"Hello, I am \" + "); src.append("this.getClass().getSimpleName();\n"); src.append(" }\n"); src.append("}\n"); System.out.println(src); DynamicEngine de = DynamicEngine.getInstance(); Object instance = de.javaCodeToObject(fullName,src.toString()); System.out.println(instance); }}
[Java]代码
package cn.outofmemory.dynamic;import javax.tools.*;import java.util.ArrayList;import java.util.List;import java.util.Arrays;import java.net.URL;import java.net.URLClassLoader;import java.io.File;public class DynamicEngine { private static DynamicEngine ourInstance = new DynamicEngine(); public static DynamicEngine getInstance() { return ourInstance; } private URLClassLoader parentClassLoader; private String classpath; private DynamicEngine() { this.parentClassLoader = (URLClassLoader) this.getClass().getClassLoader(); this.buildClassPath(); } private void buildClassPath() { this.classpath = null; StringBuilder sb = new StringBuilder(); for (URL url : this.parentClassLoader.getURLs()) { String p = url.getFile(); sb.append(p).append(File.pathSeparator); } this.classpath = sb.toString(); } public Object javaCodeToObject(String fullClassName, String javaCode) throws IllegalAccessException, InstantiationException { long start = System.currentTimeMillis(); Object instance = null; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, null, null)); List<JavaFileObject> jfiles = new ArrayList<JavaFileObject>(); jfiles.add(new CharSequenceJavaFileObject(fullClassName, javaCode)); List<String> options = new ArrayList<String>(); options.add("-encoding"); options.add("UTF-8"); options.add("-classpath"); options.add(this.classpath); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, jfiles); boolean success = task.call(); if (success) { JavaClassObject jco = fileManager.getJavaClassObject(); DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.parentClassLoader); Class clazz = dynamicClassLoader.loadClass(fullClassName,jco); instance = clazz.newInstance(); } else { String error = ""; for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { error = error + compilePrint(diagnostic); } } long end = System.currentTimeMillis(); System.out.println("javaCodeToObject use:"+(end-start)+"ms"); return instance; } private String compilePrint(Diagnostic diagnostic) { System.out.println("Code:" + diagnostic.getCode()); System.out.println("Kind:" + diagnostic.getKind()); System.out.println("Position:" + diagnostic.getPosition()); System.out.println("Start Position:" + diagnostic.getStartPosition()); System.out.println("End Position:" + diagnostic.getEndPosition()); System.out.println("Source:" + diagnostic.getSource()); System.out.println("Message:" + diagnostic.getMessage(null)); System.out.println("LineNumber:" + diagnostic.getLineNumber()); System.out.println("ColumnNumber:" + diagnostic.getColumnNumber()); StringBuffer res = new StringBuffer(); res.append("Code:[" + diagnostic.getCode() + "]\n"); res.append("Kind:[" + diagnostic.getKind() + "]\n"); res.append("Position:[" + diagnostic.getPosition() + "]\n"); res.append("Start Position:[" + diagnostic.getStartPosition() + "]\n"); res.append("End Position:[" + diagnostic.getEndPosition() + "]\n"); res.append("Source:[" + diagnostic.getSource() + "]\n"); res.append("Message:[" + diagnostic.getMessage(null) + "]\n"); res.append("LineNumber:[" + diagnostic.getLineNumber() + "]\n"); res.append("ColumnNumber:[" + diagnostic.getColumnNumber() + "]\n"); return res.toString(); }}
[Java]代码
package cn.outofmemory.dynamic;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import java.net.URI;public class CharSequenceJavaFileObject extends SimpleJavaFileObject { private CharSequence content; public CharSequenceJavaFileObject(String className, CharSequence content) { super(URI.create("string:///" + className.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE); this.content = content; } @Override public CharSequence getCharContent( boolean ignoreEncodingErrors) { return content; }}
[Java]代码
package cn.outofmemory.dynamic;import javax.tools.*;import java.io.IOException;import java.security.SecureClassLoader;public class ClassFileManager extends ForwardingJavaFileManager { public JavaClassObject getJavaClassObject() { return jclassObject; } private JavaClassObject jclassObject; public ClassFileManager(StandardJavaFileManager standardManager) { super(standardManager); } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { jclassObject = new JavaClassObject(className, kind); return jclassObject; }}
[Java]代码
package cn.outofmemory.dynamic;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import java.io.IOException;import java.io.OutputStream;import java.io.ByteArrayOutputStream;import java.net.URI;public class JavaClassObject extends SimpleJavaFileObject { protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); public JavaClassObject(String name, JavaFileObject.Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); } public byte[] getBytes() { return bos.toByteArray(); } @Override public OutputStream openOutputStream() throws IOException { return bos; }}
[Java]代码
package cn.outofmemory.dynamic;import java.net.URLClassLoader;import java.net.URL;public class DynamicClassLoader extends URLClassLoader { public DynamicClassLoader(ClassLoader parent) { super(new URL[0], parent); } public Class findClassByClassName(String className) throws ClassNotFoundException { return this.findClass(className); } public Class loadClass(String fullName, JavaClassObject jco) { byte[] classData = jco.getBytes(); return this.defineClass(fullName, classData, 0, classData.length); }}
用户点评