JavaCompiler из JDK 1.6: как записать байты класса непосредственно в массив byte []? - PullRequest
8 голосов
/ 25 января 2010

Итак, я недавно узнал о новом JavaCompiler API , доступном в JDK 1.6. Это позволяет очень просто скомпилировать String в .class файл непосредственно из исполняемого кода:

String className = "Foo";
String sourceCode = "...";

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

List<JavaSourceFromString> unitsToCompile = new ArrayList<JavaSourceFromString>() 
    {{ 
         add(new JavaSourceFromString(className, sourceCode)); 
    }};

StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
compiler.getTask(null, fileManager, null, null, null, unitsToCompile).call();
fileManager.close();    

ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(className + ".class");
IOUtils.copyStream(fis, bos);

return bos.toByteArray();

Вы можете захватить источник до JavaSourceFromString из Javadoc .

Это очень удобно скомпилирует sourceCode в Foo.class в текущем рабочем каталоге.

Мой вопрос : возможно ли скомпилировать прямо в массив byte[] и избежать беспорядка при работе с File I / O в целом?

Ответы [ 3 ]

3 голосов
/ 25 января 2010

Причиной отсутствия стандартного API для записи байт-кодов в байтовый массив является то, что компиляция одного исходного файла Java может привести к появлению нескольких файлов байт-кода. Например, любой исходный файл с вложенными / внутренними / анонимными классами приведет к нескольким файлам байт-кода.

Если вы катите свой собственный JavaFileManager, вам нужно разобраться с этой ситуацией.

3 голосов
/ 25 января 2010

Может быть, вы могли бы создать свой собственный javax.tools.JavaFileManager реализующий класс, где бы вы возвращали свою собственную реализацию javax.tools.FileObject, которая затем записывала бы ее в память вместо на диск. Так что для вашего подкласса javax.tools.FileObject Writer openWriter() throws IOException метода вы бы вернули java.io.StringWriter. Все методы должны быть преобразованы в их String аналоги.

2 голосов
/ 25 января 2010

Демонстрационное приложение, поставляемое с API JSR 199, имело пример компиляции из строки в памяти (который действительно использует MemoryFileManager). Возможно, посмотрите на это здесь или здесь (хотя эти образцы немного устарели, они потребуют небольших изменений). Также, возможно, проверьте статью Как скомпилировать на лету? на Java.net.

PS: я не смотрел на все детали, но я не думаю, что он обрабатывает случаи, упомянутые Stephen C .

...