Подтвердить что ты не робот

На лету, компиляция Java-кода в памяти для Java 5 и Java 6

Как я могу скомпилировать java-код из произвольной строки (в памяти) в Java 5 и Java 6, загрузить ее и запустить на ней определенный метод (предопределенный)?

Прежде чем вы начнете плакать, я просмотрел существующие реализации:

  • Большинство полагаются на API компилятора Java 6.
  • Те, кто этого не делает, полагаются на трюки.
  • Да, я проверил commons-jci. Либо я слишком плотный, чтобы понять, как это работает, либо просто не работает.
  • Я не мог найти, как передать компилятор моему текущему пути к классу (который довольно большой).
  • В реализации, которая работала (в Java 6), я не мог найти, как правильно загружать внутренние классы (или внутренние анонимные классы).
  • Мне бы очень понравилось, если бы все было в памяти, так как все работает в нескольких средах.

Я уверен, что это было решено раньше, но я не могу найти ничего, что бы выглядело даже полупроизводственного качества в google (кроме jci, который, как я уже говорил, мне не удалось использовать).

Изменить:

  • Я просмотрел JavaAssist - мне нужны внутренние классы, поддержка языкового уровня Java 5.0 и компиляция с помощью всего пути к классам. Кроме того, я хотел бы создавать новые классы "на лету". я может быть ошибочно, но я не мог найти, как это сделать с помощью JavaAssit.
  • Я хочу использовать решение на базе файловой системы (вызов javac), но я не знаю, как божественный путь к классам, и как позже загружать файлы (которые не входят в мой путь к классам) со специальным загрузчиком классов которые могут быть переработаны для нескольких вызовов. Хотя я действительно знаю, как его исследовать, я бы предпочел готовое решение.

Edit2: На данный момент я доволен тем, что BeanShell "оценивает". По-видимому, он делает все, что мне нужно (получить строку, оценить ее в контексте "текущего" класса. Он пропускает некоторые функции Java 5, но он может использовать перечисления (не определять) и скомпилировать "общий" (стирать), поэтому этого должно быть достаточно для того, что я хочу.

Я не хочу отмечать ответ как принятый, так как я надеюсь на лучшее решение.

Edit3: Принято предложение beanshell - оно действительно работает чудесно.

4b9b3361

Ответ 1

Если вы не полностью привязаны к компиляции, такие решения, как Beanshell, groovy и другие языки сценариев, легко внедряются (по сути, у java есть встроенная поддержка для подключения языка сценариев, поэтому ваш код не " t даже знаю, на каком языке написан script)

Beanshell должен запускать любой 100% -ный код Java IIRC, и я считаю, что groovy может запускать большинство java-кода - возможно, все.

Ответ 2

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.

Ответ 3

Возможно, вы захотите также проверить Янино.

На своем веб-сайте:

Janino - это компилятор, который считывает выражение JavaTM, блок, тело класса, исходный файл или набор исходных файлов и генерирует байт-код JavaTM, который загружается и выполняется напрямую. Janino не предназначен для разработки, но встроенный компилятор для целей компиляции во время выполнения, например. оценщики выражений или "серверные страницы", такие как JSP.

http://www.janino.net/

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

ECJ Eclipse Java Compiler

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

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

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

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