Как программно генерировать .class файлы? - PullRequest
10 голосов
/ 19 ноября 2011

Я хотел бы написать компилятор для игрушечного языка для Java.Я хотел бы создать исполняемые файлы .class.Мне было интересно, какая библиотека или лучший инструмент для этого доступны?Я знаю, что мог бы выучить двоичный формат для всех инструкций и создать свой собственный постоянный пул и т. Д., Но это похоже на работу, которая должна была быть уже сделана: нет смысла заново изобретать колесо, верно?

Поиск в Интернете IЯ нашел два разных языка ассемблера Java: Jasmin и Jamaica , однако только Jasmin выглядит несколько поддержанным.

Существует ли библиотека Java для записи байт-кодов в поток?Это то, чем является Apache BCEL ?

Является ли их инструмент для этого "стандартным" для генерации байт-кода, как Antlr для синтаксического анализа?


PS- Игрушечный язык - Brainf ***, я хотел кое-что, чтобы у меня была простая «грамматика», чтобы я мог сосредоточиться на аспекте генерации, а не на части синтаксического анализа ... это будетприходите позже на следующем шаге.

Ответы [ 4 ]

9 голосов
/ 19 ноября 2011

ASM и BCEL делают в основном похожие вещи. Я бы порекомендовал ASM, так как он гораздо более поддерживается, намного меньше и соответствует JDK.

3 голосов
/ 19 ноября 2011

Звучит так, будто вы ищете Apache BCEL :

Библиотека разработки байт-кода (Apache Commons BCEL ™) предназначена для того, чтобы предоставить пользователям удобный способ анализа, создания и управления (двоичными) файлами классов Java (заканчивающимися на .class).

2 голосов
/ 19 ноября 2011

JDK 1.6 имеет возможность динамически компилировать классы Java (см. getSystemJavaCompiler ).Это может быть использовано для компиляции Java из исходного кода без манипулирования байтовым кодом или временных файлов.Мы делаем это как способ улучшить производительность некоторого кода API отражения, но он также будет легко служить вашим целям.

Создание исходного файла Java из строки, содержащей код:

   public class JavaSourceFromString extends SimpleJavaFileObject {
       final String code;

       JavaSourceFromString(String name, String code) {
           super(URI.create("string:///"
                            + name.replace('.','/')
                            + Kind.SOURCE.extension),
                 Kind.SOURCE);
           this.code = code;
       }

       @Override
       public CharSequence getCharContent(boolean ignoreEncodingErrors) {
           return code;
       }
   }

// Use your favorite template language here, like FreeMarker
static final String sourceCode = ""
        + "import org.example.MySomethingObject;"
        // DynamicStringGetter would define getString as a standard way to get
        // a String from an object
        + "public class GetStringDynamic implements DynamicStringGetter {\n" 
        + "    public String getString(Object o) {\n"
        + "        MySomethingObject obj = (MySomethingObject) o;\n"
        + "        return o.getSomething();\n"
        + "    }\n"
        + "}\n";

   JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   StandardJavaFileManager fileManager = 
       compiler.getStandardFileManager(null, null, null);

   List<JavaFileObject> files = new ArrayList<JavaFileObject>();
   files.add(new JavaSourceFromString("org.example.DynamicClass", sourceCode));

   compiler.getTask(null, fileManager, null, null, null, files).call();

Затем вы динамически загружаете вновь созданные файлы классов.

В качестве альтернативы используйте манипулирование байтовым кодом (например, ASM ) для создания классов на лету.

В качестве другой альтернативы есть библиотека компиляции байт-кода Scala CAFEBABE .Я не использовал его лично, но он, похоже, больше ориентирован на создание нового языка JVM.

Что касается части синтаксического анализа, то Antlr должен служить.

0 голосов
/ 19 ноября 2011

Проще всего было бы перевести ваш игрушечный язык в действительный исходный код .java с помощью препроцессора, а затем просто скомпилировать его с помощью javac.Так же работает Обработка .

...