【问题标题】:getJavaFileForOutput(...) method of custom JavaFileManager not called by compiler编译器未调用自定义 JavaFileManager 的 getJavaFileForOutput(...) 方法
【发布时间】:2013-11-10 21:41:14
【问题描述】:

我有一个看起来像这样的自定义 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。

有什么建议吗??

【问题讨论】:

    标签: java linux macos glassfish-4 java-compiler-api


    【解决方案1】:

    我会在这里回答我自己的问题。

    我不敢相信这超出了我的想象,但事实证明 Windows 环境使用的是 glassfish3,而其他环境使用的是 glassfish4。发现这一点后,我使用 glassfish4 在 windows 上测试了该项目,并且能够复制我在 mac/linux 上遇到的相同问题。

    虽然这模糊地回答了我的问题,但如果我确切地找出上述代码在 glassfish4 中无法按预期工作的原因,我将在此处添加解释。

    【讨论】:

    • 大家是否在这里发现了问题的根源?我在尝试过渡到 GF 4.1 时遇到了同样的问题。谢谢。
    • 不,抱歉,我没有。我最终放弃了这段代码,寻求完全不同的解决方案。
    • 在我的例子中,将“-proc:none”添加到传递给 JavaCompiler 的选项是诀窍。为什么它起作用对我来说仍然是一个谜。调试 我确实看到加载了一些 GF 特定的注释处理器;也许这是导致问题的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    相关资源
    最近更新 更多