次のようなカスタム 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 上のグラスフィッシュでプロジェクトを実行すると、期待どおりに動作します。Mac OS X Mavericks または Centos 6.4 の Glassfish で同じプロジェクトを実行すると、getJavaFileForOutput(...) が呼び出されることはありません。私のファイルマネージャーの getClassLoader(...) メソッドは最終的に呼び出されますが、それまでには手遅れです。
getJavaFileForOuput メソッドの呼び出しを妨げている Linux+glassfish 環境の特徴は何ですか?
すべての環境が同じ jdk バージョン (jdk1.7.0_45) を使用するように正しく設定されていると確信しています。
何かアドバイス??