Оперативная компиляция Java-кода в памяти для Java 5 и Java 6
Как я могу скомпилировать код Java из произвольной строки (в памяти) в Java 5 и Java 6, загрузить его и запустить на нем определенный метод (предопределенный)?
Перед тем, как вы раскритиковали это, я просмотрел существующие реализации
- Большинство полагается на Java 6 Compiler API.
- Те, кто этого не делают, полагаются на уловки.
- Да, я проверил commons-jci. Либо я слишком туп, чтобы понять, как это работает, либо нет.
- Я не мог найти, как передать компилятору мой текущий путь к классу (который довольно большой).
- В реализации, которая работала (в Java 6), я не мог найти, как правильно загрузить внутренние классы (или внутренние анонимные классы).
- Мне бы очень хотелось, чтобы все это было в памяти, поскольку оно работает в нескольких средах.
Я уверен, что это было решено раньше, но я не могу найти ничего, что выглядит даже наполовину качественным в Google (кроме jci, который, как я уже говорил, мне не удалось использовать).
Редактировать:
- Я просмотрел JavaAssist - мне нужны внутренние классы, поддержка уровня языка Java 5.0 и компиляция со всем путем к классам. Кроме того, я хотел бы создавать новые классы на лету. Я могу ошибаться, но я не мог найти, как это сделать с помощью JavaAssit.
- Я готов использовать решение на основе файловой системы (вызывающее javac), но я не знаю, как угадать путь к классам или как впоследствии загрузить файлы (которых нет в моем пути к классам) с помощью специального загрузчика классов, который может быть переработано для нескольких вызовов. Хотя я знаю, как это исследовать, я бы предпочел готовое решение.
Edit2: на данный момент я доволен BeanShell "оценить". По-видимому, он делает все, что мне нужно (получить строку, оценить ее в контексте "текущего" пути к классам. Он пропускает некоторые функции Java 5, но может использовать перечисления (не определить) и скомпилированные "общие" (стерты)) занятия, так что должно хватить на то, что я хочу.
Я не хочу отмечать ответ как принятый, поскольку надеюсь найти лучшее решение.
Edit3: принял предложение бобов оболочки - это действительно работает чудесно.
6 ответов
Если вы не полностью привязаны к компиляции, такие решения, как Beanshell, groovy и другие языки сценариев, легко внедряются (фактически, в Java есть встроенная поддержка для подключения языка сценариев, поэтому ваш код даже не знает, какой язык сценарий написан в)
Beanshell должен выполнять любой 100% -ный Java-код IIRC, и я считаю, что Groovy может выполнять большую часть Java-кода - возможно, все.
JCI выглядит хорошо. Этот фрагмент кода должен быть вашей базой:
JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");
MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());
MemoryResourceStore mrs = new MemoryResourceStore();
CompilationResult result = compiler.compile(sources, mrr, mrs);
// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir
По какой причине это не должно работать?
Редактировать: добавил
MemoryResourceStore
отправить скомпилированный вывод класса в память, как запрошено.Также настройкаjavac
Настройки, такие как classpath в вашем случае, могут быть выполнены черезsetCustomArguments(String[] pCustomArguments)
в JavacJavaCompilerSettings
учебный класс.
Возможно, вы захотите проверить и Янино.
С их сайта:
Janino - это компилятор, который читает выражение JavaTM, блок, тело класса, исходный файл или набор исходных файлов и генерирует байт-код JavaTM, который загружается и выполняется напрямую. Janino не предназначен для разработки, но является встроенным компилятором для целей компиляции во время выполнения, например, для оценщиков выражений или механизмов "серверных страниц", таких как JSP.
Я в настоящее время использую его в довольно большом критически важном проекте, и он работает просто отлично
Запустите внутри веб-контейнера, такого как Tomcat, сначала создайте страницу JSP, а затем вызовите ее.
Это также позволяет вам избавиться от старых определений классов, просто переписав страницу JSP вместо того, чтобы ваш загрузчик классов медленно заполнялся.
Является ли требование "в памяти" из-за скорости или из-за отсутствия изменения базы кода?
Eclipse предоставляет и использует свой собственный компилятор, который не является Javac
- Компилятор Eclipse используется внутри IDE (Eclipse)
- Компилятор Eclipse может также использоваться как чистый пакетный компилятор вне Eclipse
Скомпилируйте исходный файл
$ java -jar ecj-3.5.2.jar HelloWorld.java