考慮以下(Sourced primarily from here):如何將動態編譯的字節重新編碼爲文本?
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileManager manager = new MemoryFileManager(compiler.getStandardFileManager(null, null, null));
compiler.getTask(null, manager, null, null, null, sourceScripts).call(); //sourceScripts is of type List<ClassFile>
而下面的文件管理器:
public class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
private HashMap< String, ClassFile > classes = new HashMap<>();
public MemoryFileManager(StandardJavaFileManager standardManager) {
super(standardManager);
}
@Override
public ClassLoader getClassLoader(Location location) {
return new SecureClassLoader() {
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
if (classes.containsKey(className)) {
byte[ ] classFile = classes.get(className).getClassBytes();
System.out.println(new String(classFile, "utf-8"));
return super.defineClass(className, classFile, 0, classFile.length);
} else throw new ClassNotFoundException();
}
};
}
@Override
public ClassFile getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) {
if (classes.containsKey(className)) return classes.get(className);
else {
ClassFile classObject = new ClassFile(className, kind);
classes.put(className, classObject);
return classObject;
}
}
}
public class ClassFile extends SimpleJavaFileObject {
private byte[ ] source;
protected final ByteArrayOutputStream compiled = new ByteArrayOutputStream();
public ClassFile(String className, byte[ ] contentBytes) {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
source = contentBytes;
}
public ClassFile(String className, CharSequence contentCharSequence) throws UnsupportedEncodingException {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
source = ((String)contentCharSequence).getBytes("UTF-8");
}
public ClassFile(String className, Kind kind) {
super(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind);
}
public byte[ ] getClassBytes() {
return compiled.toByteArray();
}
public byte[ ] getSourceBytes() {
return source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws UnsupportedEncodingException {
return new String(source, "UTF-8");
}
@Override
public OutputStream openOutputStream() {
return compiled;
}
}
單步調試代碼,在compiler.getTask()()調用,這裏發生的第一件事情調用getJavaFileForOutput(),然後調用getClassLoader()方法來加載類,這會在編譯後的字節中寫入控制檯。
爲什麼getClassLoader()方法中的println會產生我的工作編譯字節碼(主要是字符串,看起來實際的字節碼指令關鍵字不在這裏)和隨機亂碼的混合?這使我相信我使用的是太短的UTF,所以我嘗試了UTF-16,它看起來或多或少相似。如何將字節編碼迴文本?我知道使用SimpleJavaFileManager將會很簡單,但我需要能夠使用這個緩存示例(當然,不會出現可能的內存泄漏)以達到性能目的。
編輯: 是的,編譯後的代碼的類加載和完美運行。
啊哈,這是一個主要的銳利人。抱歉。無論如何,在那種情況下,他們的編碼是否有某種解碼器?我可以在eclipse中打開.class文件並列出操作碼,因此它必須是可能的。 – rpg711