<转> java内存动态编译执行
2013-05-08 09:33
941 查看
一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。
本例程则不需要生成任何文件,一切在内存中进行。
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
本例程则不需要生成任何文件,一切在内存中进行。
[代码] [Java]代码
[java] viewplaincopy
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
相关文章推荐
- <转>学习java反编译工具的使用
- <整理>:进程动态请求和释放内存(待)
- <Java>Java数组的声明与初始化
- <<深入理解linux内核>>读书笔记 (一): 内存寻址
- <Ibatis in action>中使用动态SQL的一个小细节提示(与CDATA)
- <为知更新>java里的throws 和 try-catch 的用法
- <Java>函数参数值传递与引用传递
- java中使用<jsp:forward>报404错误
- Java笔记7 Java基础加强<5>ClassLoader
- JS -- <table> 行号自增,前端动态生成的<tr>
- <java——继承>
- java - JNI - 【 java <-> C++ String 的转换 】
- java之重载和重写<一>
- <a>标签跳转到action中action连续执行2次
- <Java>一个类bytebuffer使用
- UBUNTU12.04编译Android源码<命令行>:0:0: 错误: “_FORTIFY_SOURCE”重定义 [-Werror] <命令行>::0:0: 错误: “_FORTIFY_SOUR
- <Android+Java>Eclipse导入包的快捷键
- <转>,防止刷新/后退引起的重复提交问题的Java Token代码,非Struts
- Hadoop中文件读写(Java) &lt;转&gt;
- Java笔记7 Java基础加强<6>加密