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

一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。
本例程则不需要生成任何文件,一切在内存中进行。

[代码] [Java]代码

 
[java]  view plain copy
  1. package com;  
  2.   
  3. public class DynaCompTest {  
  4.     public static void main(String[] args) throws Exception {  
  5.         String fullName = "DynaClass";  
  6.         StringBuilder src = new StringBuilder();  
  7.         src.append("public class DynaClass {\n");  
  8.         src.append("    public String toString() {\n");  
  9.         src.append("        return \"Hello, I am \" + ");  
  10.         src.append("this.getClass().getSimpleName();\n");  
  11.         src.append("    }\n");  
  12.         src.append("}\n");  
  13.   
  14.         System.out.println(src);  
  15.         DynamicEngine de = DynamicEngine.getInstance();  
  16.         Object instance =  de.javaCodeToObject(fullName,src.toString());  
  17.         System.out.println(instance);  
  18.     }  
  19. }  
[java]  view plain copy
  1. package com;  
  2.   
  3. import javax.tools.*;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6. import java.util.Arrays;  
  7. import java.net.URL;  
  8. import java.net.URLClassLoader;  
  9. import java.io.File;  
  10.   
  11. public class DynamicEngine {  
  12.     private static DynamicEngine ourInstance = new DynamicEngine();  
  13.   
  14.     public static DynamicEngine getInstance() {  
  15.         return ourInstance;  
  16.     }  
  17.     private URLClassLoader parentClassLoader;  
  18.     private String classpath;  
  19.     private DynamicEngine() {  
  20.         this.parentClassLoader = (URLClassLoader) this.getClass().getClassLoader();  
  21.         this.buildClassPath();  
  22.     }  
  23.     private void buildClassPath() {  
  24.         this.classpath = null;  
  25.         StringBuilder sb = new StringBuilder();  
  26.         for (URL url : this.parentClassLoader.getURLs()) {  
  27.             String p = url.getFile();  
  28.             sb.append(p).append(File.pathSeparator);  
  29.         }  
  30.         this.classpath = sb.toString();  
  31.     }  
  32.     public Object javaCodeToObject(String fullClassName, String javaCode) throws IllegalAccessException, InstantiationException {  
  33.         long start = System.currentTimeMillis();  
  34.         Object instance = null;  
  35.         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
  36.         DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();  
  37.         ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, nullnull));  
  38.   
  39.         List<JavaFileObject> jfiles = new ArrayList<JavaFileObject>();  
  40.         jfiles.add(new CharSequenceJavaFileObject(fullClassName, javaCode));  
  41.   
  42.         List<String> options = new ArrayList<String>();  
  43.         options.add("-encoding");  
  44.         options.add("UTF-8");  
  45.         options.add("-classpath");  
  46.         options.add(this.classpath);  
  47.   
  48.         JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, jfiles);  
  49.         boolean success = task.call();  
  50.   
  51.         if (success) {  
  52.             JavaClassObject jco = fileManager.getJavaClassObject();  
  53.             DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.parentClassLoader);  
  54.             Class clazz = dynamicClassLoader.loadClass(fullClassName,jco);  
  55.             instance = clazz.newInstance();  
  56.         } else {  
  57.             String error = "";  
  58.             for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {  
  59.                 error = error + compilePrint(diagnostic);  
  60.             }  
  61.         }  
  62.         long end = System.currentTimeMillis();  
  63.         System.out.println("javaCodeToObject use:"+(end-start)+"ms");  
  64.         return instance;  
  65.     }  
  66.   
  67.     private String compilePrint(Diagnostic diagnostic) {  
  68.         System.out.println("Code:" + diagnostic.getCode());  
  69.         System.out.println("Kind:" + diagnostic.getKind());  
  70.         System.out.println("Position:" + diagnostic.getPosition());  
  71.         System.out.println("Start Position:" + diagnostic.getStartPosition());  
  72.         System.out.println("End Position:" + diagnostic.getEndPosition());  
  73.         System.out.println("Source:" + diagnostic.getSource());  
  74.         System.out.println("Message:" + diagnostic.getMessage(null));  
  75.         System.out.println("LineNumber:" + diagnostic.getLineNumber());  
  76.         System.out.println("ColumnNumber:" + diagnostic.getColumnNumber());  
  77.         StringBuffer res = new StringBuffer();  
  78.         res.append("Code:[" + diagnostic.getCode() + "]\n");  
  79.         res.append("Kind:[" + diagnostic.getKind() + "]\n");  
  80.         res.append("Position:[" + diagnostic.getPosition() + "]\n");  
  81.         res.append("Start Position:[" + diagnostic.getStartPosition() + "]\n");  
  82.         res.append("End Position:[" + diagnostic.getEndPosition() + "]\n");  
  83.         res.append("Source:[" + diagnostic.getSource() + "]\n");  
  84.         res.append("Message:[" + diagnostic.getMessage(null) + "]\n");  
  85.         res.append("LineNumber:[" + diagnostic.getLineNumber() + "]\n");  
  86.         res.append("ColumnNumber:[" + diagnostic.getColumnNumber() + "]\n");  
  87.         return res.toString();  
  88.     }  
  89. }  
[java]  view plain copy
  1. package com;  
  2.   
  3. import javax.tools.JavaFileObject;  
  4. import javax.tools.SimpleJavaFileObject;  
  5. import java.net.URI;  
  6.   
  7. public class CharSequenceJavaFileObject extends SimpleJavaFileObject {  
  8.   
  9.     private CharSequence content;  
  10.   
  11.   
  12.     public CharSequenceJavaFileObject(String className,  
  13.                                       CharSequence content) {  
  14.         super(URI.create("string:///" + className.replace('.''/')  
  15.                 + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE);  
  16.         this.content = content;  
  17.     }  
  18.   
  19.     @Override  
  20.     public CharSequence getCharContent(  
  21.             boolean ignoreEncodingErrors) {  
  22.         return content;  
  23.     }  
  24. }  
[java]  view plain copy
  1. package com;  
  2.   
  3. import javax.tools.*;  
  4. import java.io.IOException;  
  5. import java.security.SecureClassLoader;  
  6.   
  7. public class ClassFileManager extends  
  8.         ForwardingJavaFileManager {  
  9.     public JavaClassObject getJavaClassObject() {  
  10.         return jclassObject;  
  11.     }  
  12.   
  13.     private JavaClassObject jclassObject;  
  14.   
  15.   
  16.     public ClassFileManager(StandardJavaFileManager  
  17.         standardManager) {  
  18.         super(standardManager);  
  19.     }  
  20.   
  21.   
  22.     @Override  
  23.     public JavaFileObject getJavaFileForOutput(Location location,  
  24.         String className, JavaFileObject.Kind kind, FileObject sibling)  
  25.             throws IOException {  
  26.             jclassObject = new JavaClassObject(className, kind);  
  27.         return jclassObject;  
  28.     }  
  29. }  
[java]  view plain copy
  1. package com;  
  2.   
  3. import javax.tools.JavaFileObject;  
  4. import javax.tools.SimpleJavaFileObject;  
  5. import java.io.IOException;  
  6. import java.io.OutputStream;  
  7. import java.io.ByteArrayOutputStream;  
  8. import java.net.URI;  
  9.   
  10. public class JavaClassObject extends SimpleJavaFileObject {  
  11.   
  12.     protected final ByteArrayOutputStream bos =  
  13.         new ByteArrayOutputStream();  
  14.   
  15.   
  16.     public JavaClassObject(String name, JavaFileObject.Kind kind) {  
  17.         super(URI.create("string:///" + name.replace('.''/')  
  18.             + kind.extension), kind);  
  19.     }  
  20.   
  21.   
  22.     public byte[] getBytes() {  
  23.         return bos.toByteArray();  
  24.     }  
  25.   
  26.     @Override  
  27.     public OutputStream openOutputStream() throws IOException {  
  28.         return bos;  
  29.     }  
  30. }  
[java]  view plain copy
  1. package com;  
  2.   
  3. import java.net.URLClassLoader;  
  4. import java.net.URL;  
  5.   
  6. public class DynamicClassLoader extends URLClassLoader {  
  7.     public DynamicClassLoader(ClassLoader parent) {  
  8.         super(new URL[0], parent);  
  9.     }  
  10.   
  11.     public Class findClassByClassName(String className) throws ClassNotFoundException {  
  12.         return this.findClass(className);  
  13.     }  
  14.   
  15.     public Class loadClass(String fullName, JavaClassObject jco) {  
  16.         byte[] classData = jco.getBytes();  
  17.         return this.defineClass(fullName, classData, 0, classData.length);  
  18.     }  
  19. }  

 

转至  http://www.oschina.net/code/snippet_220184_8607


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值