编译器未调用自定义JavaFileManager的getJavaFileForOutput(...)方法 [英] getJavaFileForOutput(...) method of custom JavaFileManager not called by compiler

查看:139
本文介绍了编译器未调用自定义JavaFileManager的getJavaFileForOutput(...)方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义JavaFileManager,看起来像这样:

I have a custom JavaFileManager that looks something like this:

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(...)方法.

I have redacted a lot of code for readability purposes; the class also implements the list(...) method and the inferBinaryName(...) method.

在我项目的另一个区域中,我运行类似于以下内容的内容:

In another area of my project I run something similar to the following:

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(...)方法最终被调用,但是那时为时已晚.

If I run some junit tests in eclipse on windows/mac/linux it works exactly as I would expect. If I run my project in glassfish on windows it also works exactly how I would expect. If I run the same project in glassfish on Mac OS X Mavericks or Centos 6.4 the getJavaFileForOutput(...) is simply never called! The getClassLoader(...) method of my file manager is eventually called but by then it is too late.

Linux + glassfish环境有什么独特之处,可以阻止我的getJavaFileForOuput方法被调用?

What is unique about the linux+glassfish environment that is preventing my getJavaFileForOuput method from being called?

我很确定我已经正确设置了所有环境以使用相同的jdk版本:jdk1.7.0_45.

I'm pretty sure I have all environments correctly set up to use the same jdk version: jdk1.7.0_45.

有什么建议吗?

推荐答案

我将在这里回答我自己的问题.

I'll answer my own question here.

我简直不敢相信这一点,但事实证明Windows环境使用的是glassfish3,而其他环境使用的是glassfish4.一旦发现这一点,便可以使用glassfish4在Windows上测试该项目,并且能够复制在Mac/Linux上遇到的相同问题.

I can't believe this went over my head but it turns out the Windows environment was using glassfish3 whereas the other environments were using glassfish4. Once I discovered this, I tested the project on windows using glassfish4 and I was able to replicate the same issue I experience on mac/linux.

虽然模糊地回答了我的问题,但是,如果我确切地找到了为什么上面的代码不能在glassfish4中按预期方式工作,我将在此处添加一个解释.

While that vaguely answers my question, if I find out exactly why the above code does not work as expected in glassfish4, I will add an explanation here.

这篇关于编译器未调用自定义JavaFileManager的getJavaFileForOutput(...)方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆