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 {
");   source.append("    public boolean m(String v) {
");   source.append("        return \"e2say\".equals(v);
");   source.append("    }
");   source.append("    public int m(int v) {
");   source.append("        return v*((v+1)-2*3/4);
");   source.append("    }
");   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() + "
");     buf.append("Kind:" + diagnostic.getKind() + "
");     buf.append("Position:" + diagnostic.getPosition() + "
");     buf.append("Start Position:" + diagnostic.getStartPosition() + "
");     buf.append("End Position:" + diagnostic.getEndPosition() + "
");     buf.append("Source:" + diagnostic.getSource() + "
");     buf.append("Message:" + diagnostic.getMessage(null) + "
");     buf.append("LineNumber:" + diagnostic.getLineNumber() + "
");     buf.append("ColumnNumber:" + diagnostic.getColumnNumber() + "
");     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);   }  } }