Вопрос

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

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

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

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

Редактировать:

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

Джей Си выглядит прекрасно.Этот фрагмент кода должен быть вашей базой:

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

Есть какая-нибудь причина, по которой это не должно сработать?


Редактировать: добавил a MemoryResourceStore отправить скомпилированный вывод класса в память, как и было запрошено.

Кроме того, настройка javac настройки, такие как classpath в вашем случае, могут быть выполнены с помощью setCustomArguments(String[] pCustomArguments) в JavacJavaCompilerSettings класс.

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

С их веб-сайта:

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

http://www.janino.net/

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

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

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

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

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

Компилятор Java ECJ Eclipse

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top