Оперативная компиляция 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.

http://www.janino.net/

Я в настоящее время использую его в довольно большом критически важном проекте, и он работает просто отлично

Javassist может вас заинтересовать

Запустите внутри веб-контейнера, такого как Tomcat, сначала создайте страницу JSP, а затем вызовите ее.

Это также позволяет вам избавиться от старых определений классов, просто переписав страницу JSP вместо того, чтобы ваш загрузчик классов медленно заполнялся.

Является ли требование "в памяти" из-за скорости или из-за отсутствия изменения базы кода?

ECJ Eclipse Java Compiler

Eclipse предоставляет и использует свой собственный компилятор, который не является Javac

  • Компилятор Eclipse используется внутри IDE (Eclipse)
  • Компилятор Eclipse может также использоваться как чистый пакетный компилятор вне Eclipse

Скомпилируйте исходный файл

$ java -jar ecj-3.5.2.jar HelloWorld.java

Другие вопросы по тегам