компиляция класса java в памяти на лету (и загрузка)

Я хочу вернуться к своему старому вопросу о «компиляции» классов в памяти. Поскольку прошло около 1/2 года с тех пор, как я спросил (и получил несколько ответов), я хотел бы повторно поднять вопрос и посмотреть, не появится ли что-то новое (поэтому нет, я не считаю это дубликатом) .

Старый вопрос можно найти здесь: Оперативная компиляция Java-кода в памяти для Java 5 и Java 6 – советую прочитать ее (и ответы) перед ответом на этот вопрос.

Я вполне доволен тем, что beanshell выполняет тяжелую работу по оценке строки класса java для фактического объекта класса. Тем не менее, beanshell уже давно стоит на версии 2.0b4, и его ограничения (без конструктора, даже по умолчанию; без дженериков, без for-each, без перечислений...) раздражают.

Напоминание: это должно использоваться в качестве интерфейса отладки, поэтому соображения производительности незначительны. Тем не менее, я не могу перезапускать сервер, не могу отправлять файлы классов в местоположение, и JSP - очень плохой выбор для меня (я не буду здесь вдаваться в причины). Кроме того, конечный продукт должен быть классом (или объектом этого класса), чтобы я мог передавать его.

Некоторые ограничения: у меня не может быть JDK, поэтому нет javax.tools.JavaCompiler. У меня не может быть JSP, так как у меня нет tomcat или другого «настоящего» веб-контейнера. Поддержка синтаксиса Java 5 была бы отличной, особенно дженерики, перечисления и параметризация. Поддержка конструкторов по умолчанию была бы очень кстати.

Любые идеи?

Редактировать 1: я только что узнал, что существует обходной способ иметь конструкторы в beanshell, однако вы должны объявить их "public void XXX(){...}" вместо обычного способа "public XXX(){ ...}".


person Ran Biron    schedule 24.11.2009    source источник


Ответы (5)


Если вы не можете связать SUN JDK tools.jar из-за лицензионных соображений, возможно, вместо этого вы могли бы включить компилятор Eclipse JDT Core, см.

http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm

Это напр. что делает реализация JSP веб-сервера Jetty.

person Stefan L    schedule 24.11.2009
comment
Ну, я сделал. Это потребовало бы от меня либо: 1. зависимости непосредственно от JDT, что является проблемой для меня (уровень организации), либо 2. зависимости от внутренних компонентов причала, которые не гарантированно не изменятся. Спасибо, в любом случае - person Ran Biron; 26.11.2009

Разве вы не можете просто скопировать в tools.jar, получить javax.tools.JavaCompiler и добавить его в путь к классам? Или это вопрос лицензии.

Этот код и tools.jar в пути к классам работают:

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


public class Main
{
    public static void main(final String[] argv)
        throws IOException
    {
        final File[]                             files;
        final JavaCompiler                       compiler;
        final StandardJavaFileManager            fileManager;
        final Iterable<? extends JavaFileObject> compilationUnits;

        files = new File[]
        {
            new File(argv[0]),
        };        
        compiler         = ToolProvider.getSystemJavaCompiler();
        fileManager      = compiler.getStandardFileManager(null, null, null);
        compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files));

        compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
        fileManager.close();
    }
}
person TofuBeer    schedule 24.11.2009
comment
Нет. Проблема с лицензией. Кроме того, клиент может изменить JRE, с которой работает мой сервер, так что это также проблема совместимости. - person Ran Biron; 25.11.2009

Я помню, как давным-давно читал об инженерной библиотеке байт-кода (BCEL), когда Java 1.4 была в моде. См. http://jakarta.apache.org/bcel/index.html. Я никогда не использовал его, поэтому я упоминаю его только потому, что он кажется близким к тому, о чем вы спрашиваете (и он работает или, по крайней мере, работал со старыми виртуальными машинами), и я еще не видел, чтобы кто-нибудь упоминал об этом.

person Gabe Johnson    schedule 24.11.2009
comment
Изучил бы это. Однако это не похоже на действительное решение - слишком много накладных расходов. - person Ran Biron; 25.11.2009

Есть ли конкретная причина, по которой это должна быть строка Java, создающая класс/объект? Моей спонтанной реакцией было то, что JRuby — это то, что вы ищете — кажется, это очень надежная платформа, а в Ruby сильны традиции метапрограммирования.

person gustafc    schedule 25.11.2009
comment
Должна быть строка Java, так как это знают все разработчики. Я хочу написать плагин, который будет подключаться к работающему серверу и помогать его отлаживать (создавать сообщения журнала, запрашивать внутренние структуры и т. д.). Принуждение всех к изучению руби сделает его устаревшим еще до того, как он начнется (никто не выучит - никто не будет его использовать). - person Ran Biron; 25.11.2009
comment
Как грустно - она ​​подошла бы вам как влитая. Как вы заметили, есть причина, по которой Java обычно не используется для написания сценариев. Я предполагаю, что о Groovy и JavaScript (оба более похожи на Java, чем на Ruby) тоже не может быть и речи? - person gustafc; 25.11.2009
comment
@gustafc: да, по тем же причинам. - person Ran Biron; 25.11.2009

Я закончил тем, что использовал Bean Shell. Это не идеально, но решило 99% проблемы.

person Ran Biron    schedule 26.05.2011