您的位置:首页 > 编程语言 > Java开发

<转> java内存动态编译执行

2013-05-08 09:33 941 查看
一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。

本例程则不需要生成任何文件,一切在内存中进行。

[代码] [Java]代码

[java] view
plaincopy

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);

}

}

[java] view
plaincopy

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();

}

}

[java] view
plaincopy

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;

}

}

[java] view
plaincopy

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;

}

}

[java] view
plaincopy

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;

}

}

[java] view
plaincopy

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

代码下载:http://download.csdn.net/detail/b275518834/5343251
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: