一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。
本例程则不需要生成任何文件,一切在内存中进行。
本例程则不需要生成任何文件,一切在内存中进行。
[代码] [Java]代码
- package com;
- 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);
- }
- }
- package com;
- 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();
- }
- }
- package com;
- 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;
- }
- }
- package com;
- 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;
- }
- }
- package com;
- 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;
- }
- }
- package com;
- 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);
- }
- }
转至 http://www.oschina.net/code/snippet_220184_8607