JavaCompiler из JDK 1.6:как записать байты класса непосредственно в массив byte[]?
-
22-09-2019 - |
Вопрос
Итак, недавно я узнал о новом По API JavaCompiler доступно в JDK 1.6.Это очень упрощает компиляцию String
к a .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
Ввод-вывод в целом?
Решение
Может быть, вы могли бы создать свой собственный javax.tools.JavaFileManager
реализующий класс, в котором вы бы вернули свою собственную реализацию javax.tools.FileObject
который затем запишет его в память, а не на диск.Итак, для вашего подкласса javax.tools.FileObject
Writer openWriter() throws IOException
метод, который вы бы вернули java.io.StringWriter
.Все методы должны быть преобразованы в их String
аналоги.
Другие советы
Причина, по которой не существует стандартного API для записи байт-кодов в байтовый массив, заключается в том, что компиляция одного исходного файла Java может привести к созданию нескольких файлов байт-кодов.Например, любой исходный файл с вложенными / внутренними / анонимными классами приведет к созданию нескольких файлов байт-кода.
Если вы создадите свой собственный JavaFileManager, вам нужно будет разобраться с этой ситуацией.
Демонстрационное приложение, поставляемое с API JSR 199, содержало пример компиляции из строки в памяти (который действительно использует MemoryFileManager
).Может быть, взглянете на это здесь или здесь (хотя эти образцы немного устарели, они потребуют незначительных изменений).Также, возможно, проверьте Как скомпилировать "на лету"? статья о Java.net .
PS:Я не рассматривал все детали, но я не думаю, что он обрабатывает случаи, упомянутые Стивен Си.