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);
}
}
}
转载于:https://my.oschina.net/h2do/blog/268089