我有一个看起来像这样的自定义 JavaFileManager:
public class InMemoryForwardingFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private final Map<String, ByteArrayJavaFileObject> javaFileObjects = new HashMap<>();
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException{
JavaFileObject fileObject = new ByteArrayJavaFileObject( ... );
javaFileObjects.put(className, fileObject);
return fileObject;
}
@Override
public ClassLoader getClassLoader(Location location){
return new SecureClassLoader(InMemoryForwardingFileManager.class.getClassLoader()){
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
ByteArrayJavaFileObject fileObject = javaFileObjects.get(name);
if(fileObject != null){
byte[] bytes = fileObject.getBytes();
return defineClass(name, bytes, 0, bytes.length);
} else{
throw new ClassNotFoundException();
}
}
}
}
}
为了便于阅读,我编辑了很多代码;该类还实现了 list(...) 方法和 inferBinaryName(...) 方法。
在我项目的另一个领域,我运行类似于以下内容的内容:
InMemoryForwardingFileManager fileManager = // get singleton instance
... // declare compilation units, options, diagnostic listener, etc
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostics, compilationOptions, null, compilationUnits);
compilerTask.call();
// load and instantiate the compiled class
ClassLoader classLoader = fileManager.getClassLoader(null);
MyGeneratedClass instance = (MyGeneratedClass) classLoader.loadClass(fullClassName).newInstance();
如果我在 windows/mac/linux 上的 eclipse 中运行一些 junit 测试,它的工作原理完全符合我的预期。如果我在 windows 上的 glassfish 中运行我的项目,它也完全符合我的预期。如果我在 Mac OS X Mavericks 或 Centos 6.4 上的 glassfish 中运行相同的项目,getJavaFileForOutput(...) 根本就不会被调用!我的文件管理器的 getClassLoader(...) 方法最终被调用,但到那时为时已晚。
阻止调用我的 getJavaFileForOuput 方法的 linux+glassfish 环境有什么独特之处?
我很确定我已正确设置所有环境以使用相同的 jdk 版本:jdk1.7.0_45。
有什么建议吗??