2013-11-10 4 views
2

У меня есть пользовательский JavaFileManager, который выглядит примерно так:getJavaFileForOutput (...) метод пользовательского 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(); 
       } 

      } 

     } 

    } 
} 

Я отредактированный много кода для целей удобства чтения; класс также реализует метод списка (...) и метод 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(); 

Если я запустить несколько тестов JUnit в затмении на Windows/Mac/Linux он работает именно так, как я бы ожидать. Если я запускаю свой проект в стеклянную рыбку на окнах, он также работает точно так, как я ожидал бы. Если я запускаю тот же проект в стеклянной планете на Mac OS X Mavericks или Centos 6.4, getJavaFileForOutput (...) просто никогда не вызывается! Метод getClassLoader (...) моего файлового менеджера в конечном итоге вызван, но к тому времени уже слишком поздно.

Что уникально в среде linux + glassfish, которая мешает моему методу getJavaFileForOuput быть вызванным?

Я уверен, что у меня есть все окружения, которые правильно настроены для использования одной и той же версии jdk: jdk1.7.0_45.

Любые советы ??

ответ

0

Я отвечу на свой вопрос здесь.

Я не могу поверить, что это пошло по моей голове, но оказалось, что в среде Windows использовалась стеклянная рыба 3, тогда как в других средах использовалась стеклянная рыба4. Как только я это обнаружил, я протестировал проект на windows, используя glassfish4, и мне удалось воспроизвести ту же самую проблему, что и на mac/linux.

Хотя это неопределенно отвечает на мой вопрос, если я точно выясню, почему приведенный выше код не работает, как ожидалось, в glassfish4, я добавлю объяснение здесь.

+0

Вы все нашли здесь источник проблемы? Я сталкиваюсь с этой же проблемой при попытке перехода на GF 4.1. Благодарю. – Pete

+0

Не жалко, я этого не делал. Я оставил этот код для радикально другого решения. – mbosecke

+1

В моем случае добавление '-proc: none' к параметрам, переданным в JavaCompiler, было трюком. Почему это работает, по-прежнему остается загадкой для меня. Отладка Я видел несколько загруженных процессоров конкретных GF; возможно, это и вызывало проблему. – Pete