java内存动态编译

public class MemoryCompiler {
 private static MemoryCompiler compiler = new MemoryCompiler();
 private MemoryCompiler(){
 }
 public static MemoryCompiler getInstance(){
  return compiler;
 }
 
 public static void main(String[] args) throws Throwable{
  StringBuilder source = new StringBuilder();
  source.append("public class MemoryClass {\n");
  source.append("    public boolean m(String v) {\n");
  source.append("        return \"e2say\".equals(v);\n");
  source.append("    }\n");
  source.append("    public int m(int v) {\n");
  source.append("        return v*((v+1)-2*3/4);\n");
  source.append("    }\n");
  source.append("}");
  System.out.println(source);
  
  /*1、编译*/
  Class<?> cls = getInstance().compile("MemoryClass", source.toString());
  /*2、实例化*/
  Object obj = cls.newInstance();
  /*3、方法调用*/
  Object rtn1 = cls.getMethod("m", String.class).invoke(obj, "e2say");
  System.out.println("m(\"e2say\"):"+rtn1);
  Object rtn2 = cls.getMethod("m", int.class).invoke(obj, 10);
  System.out.println("m(10):"+rtn2);
 }
 
 public Class<?> compile(String className, String content) throws Throwable{
  JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
  ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, null, null));
  
  URLClassLoader classLoader = (URLClassLoader) JinGuo.class.getClassLoader();
  StringBuilder classPath = new StringBuilder();
  for(URL url:classLoader.getURLs()){
   classPath.append(url.getFile()).append(File.pathSeparator);
  }
  //System.out.println(classPath);
  
  JavaCompiler.CompilationTask task = compiler.getTask(null, 
    fileManager, 
    diagnostics, 
    Arrays.asList("-encoding", "UTF-8", "-classpath", classPath.toString()), 
    null, 
    Arrays.asList(new JavaSourceObject(className, content)));
  
  if(task.call()){
   
   MemoryClassLoader loader = new MemoryClassLoader(classLoader);
   
   JavaClassObject classObject = fileManager.getJavaClassObject(className);
   Class<?> cls = loader.loadClass(className, classObject);
   return cls;
   
  }else{
   
   for(Diagnostic<? extends JavaFileObject> diagnostic:diagnostics.getDiagnostics()){
    StringBuffer buf = new StringBuffer();
    buf.append("Code:" + diagnostic.getCode() + "\n");
    buf.append("Kind:" + diagnostic.getKind() + "\n");
    buf.append("Position:" + diagnostic.getPosition() + "\n");
    buf.append("Start Position:" + diagnostic.getStartPosition() + "\n");
    buf.append("End Position:" + diagnostic.getEndPosition() + "\n");
    buf.append("Source:" + diagnostic.getSource() + "\n");
    buf.append("Message:" + diagnostic.getMessage(null) + "\n");
    buf.append("LineNumber:" + diagnostic.getLineNumber() + "\n");
    buf.append("ColumnNumber:" + diagnostic.getColumnNumber() + "\n");
    System.out.println(buf.toString());
   }
  }
  
  return null;
 }
 /**文件内容为内存中动态拼出的字符串*/
 private class JavaSourceObject extends SimpleJavaFileObject {
  private CharSequence content;
  public JavaSourceObject(String className, CharSequence content) {
   super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
   this.content = content;
  }
  @Override
  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   return content;
  }
 }
 /**编译时class输出至JavaClassObject的ByteArrayOutputStream*/
 private class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
  
  public ClassFileManager(StandardJavaFileManager standardManager) {
   super(standardManager);
  }
  
  private HashMap<String,JavaClassObject> classMap = new HashMap<String,JavaClassObject>();
  public JavaClassObject getJavaClassObject(String className) {
   return classMap.get(className);
  }
  @Override
  public JavaFileObject getJavaFileForOutput(Location location, String className, 
    JavaFileObject.Kind kind, FileObject sibling) throws IOException {
   JavaClassObject classObject = new JavaClassObject(className, kind);
   classMap.put(className, classObject);
   return classObject;
  }
 }
 private class JavaClassObject extends SimpleJavaFileObject {
  protected final ByteArrayOutputStream bos = new ByteArrayOutputStream();
  public JavaClassObject(String name, 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;
  }
 }
 /**从内存加载类*/
 private class MemoryClassLoader extends URLClassLoader {
  public MemoryClassLoader(ClassLoader parent) {
   super(new URL[0], parent);
  }
  public Class<?> loadClass(String className, JavaClassObject classObject) {
   byte[] bytes = classObject.getBytes();
   //defineClass方法为protected
   return defineClass(className, bytes, 0, bytes.length);
  }
 }
}

你可能感兴趣的:(动态编译)