Как я могу скомпилировать и развернуть Java-класс во время выполнения?
Я нахожусь в процессе написания механизма правил, который выполняет простые назначения, как определено условными конструкциями. Обязательным условием проекта является наличие правил в формате XML. Я смоделировал мою схему XML, чтобы она напоминала простые блоки кода. Я хочу проанализировать XML и затем преобразовать его в код Java. Затем я хочу скомпилировать (и запустить) этот код во время выполнения. Это будет означать, что мой механизм правил больше не действует как интерпретатор, а выполняет собственный Java-байт-код.
Я выяснил стадию синтаксического анализа и более или менее фазу генерации Java-кода. Теперь я хотел бы выяснить последний этап - компиляция на этапе выполнения.
Следующий поток: Компилировать в байт-код Java (без использования Java). Мне стало известно о следующих возможных решениях:
Я хотел бы сравнить их, а также другие предложения для решения компиляции Java на этапе выполнения.
7 ответов
Вы можете преобразовать его в код Clojure, и компилятор Clojure превратит его в байт-код для вас.
Вот утилита компиляции Java, вы можете скомпилировать свой код во время выполнения без какого-либо инструмента байт-кода
Javassist - это почти полный компилятор Java, написанный на Java, и он полностью сделан из Java. Вы не можете дать ему целый файл.java сразу, но вы можете дать ему строку кода для отдельных функций и добавить их в тот же объект CtClass, который становится байт-кодом, а затем java.lang.Class.
Я только что выпустил версию 0.1 GigaLineCompile, которая использует Javassist (компилятор) и Beanshell (интерпретатор) вместе и дает вам контроль над тем, какой код оптимизировать и когда. В более поздних версиях он будет меняться между Javassist и Beanshell с меньшей степенью детализации, поэтому, если у вас есть много строк кода, которые совместно используют некоторые подстроки, подстроки будут скомпилированы, а другие части будут выполняться в beanshell. Он в основном полезен для искусственного интеллекта, который генерирует код Java, но также является альтернативой Clojure или крайностям только Javassist/Beanshell.
Javassist, Beanshell и GigaLineCompile можно загрузить (с источником) здесь: http://sourceforge.net/projects/gigalinecompile
Groovy, BeanShell или любой другой язык сценариев, основанный на JVM, имеют такую возможность для вставки, изменения, добавления и запуска кода во время выполнения. На самом деле все скриптовые языки интерпретируются, поэтому на самом деле они не компилируются во время выполнения.
Избавьте себя от хлопот и используйте BeanShell, как указано здесь. Выполнение Java-кода, приведенного в текстовом файле.
Что такое BeanShell?
BeanShell - это небольшой бесплатный встраиваемый интерпретатор исходного кода Java с функциями языка объектных сценариев, написанный на Java. BeanShell динамически выполняет стандартный синтаксис Java и дополняет его обычными сценариями, такими как свободные типы, команды и замыкания методов, такие как в Perl и JavaScript.
Вы можете использовать BeanShell в интерактивном режиме для экспериментов и отладки Java, а также для расширения ваших приложений новыми способами. Сценарии Java подходит для широкого круга приложений, включая быстрое создание прототипов, расширение пользовательских сценариев, механизмы правил, конфигурацию, тестирование, динамическое развертывание, встроенные системы и даже обучение Java.
BeanShell небольшой и встраиваемый, поэтому вы можете вызывать BeanShell из ваших Java-приложений для динамического выполнения Java-кода во время выполнения или для обеспечения расширяемости в ваших приложениях. В качестве альтернативы вы можете использовать автономные скрипты BeanShell для манипулирования Java-приложениями; работа с объектами Java и API динамически. Поскольку BeanShell написан на Java и работает в той же виртуальной машине, что и ваше приложение, вы можете свободно передавать ссылки на "живые" объекты в сценарии и возвращать их в качестве результатов.
Короче говоря, BeanShell - это динамически интерпретируемая Java, а также язык сценариев и гибкая среда, объединенные в один чистый пакет.
Вы можете раскошелиться на такой процесс
Process p = Runtime.getRuntime().exec("java -classpath "..." SomeClassContainingMain ...other arguments);
//you need to consume the outputs of the command if output/error is large otherwise the process is going to hang if output/error buffer is full. and create a seperate thead for it (not created here).
log.debug("PROCESS outputstream : " + p.getInputStream() );
log.debug("PROCESS errorstream : " + p.getErrorStream());
p.waitFor(); // Wait till the process is finished
и может скомпилировать и запустить его.