Внутренняя архитектура компилятора Java

Я работал над Java с более чем 8 лет.

На прошлой неделе на небольшом собрании в моей компании один из моих коллег спросил меня, как именно Java Compiler Работа? Я был без ответа.

Я попытался объяснить, как Java Compiler принимает операторы один за другим и преобразует их в байтовый код, который не предназначен ни для каких OS но JVM,

Никто не удовлетворен этим ответом, даже я.

Теперь главный вопрос - как именно работает компилятор Java. т.е. сколько шагов или этапов или фаз есть, что будет сделано компилятором в случае компиляции Java файл.

Что именно Java's compiler архитектура?

Что делать, если есть несколько Java classes в том же файле.java. Тогда сколько классов будет скомпилировано.

Что делать, если есть импорт, указывающий на не скомпилированные классы Java? Тогда некомпилированные классы будут скомпилированы или проигнорированы?

Я гуглил больше половины дня, и все дают тот же ответ, что и моим коллегам.

Но, наконец, я нашел здесь полезное руководство.

Но учебник также охватывал не слишком углубленно, и я не смог визуализировать этот учебник.

Тем не менее, я не удовлетворен и не хочу узнать что-то еще об этом от вас.

Так что, если кто-то знает что-то большее, чем я и вышеупомянутый блог, что-то, с помощью которого я могу визуализировать, что именно внутренняя архитектура Java Compiler пожалуйста, объясните мне.

2 ответа

Решение

Некоторые основные шаги:

  1. parse: читает набор исходных файлов *.java и отображает полученную последовательность токенов в узлы AST (абстрактное синтаксическое дерево).
  2. enter: ввод символов для определений в таблицу символов.
  3. Обрабатывать аннотации: если требуется, обрабатывает аннотации, найденные в указанных единицах компиляции.
  4. Атрибут: Атрибуты деревьев синтаксиса. Этот шаг включает в себя разрешение имен, проверку типов и постоянное свертывание.
  5. flow: выполняет анализ потока данных на деревьях из предыдущего шага. Это включает в себя проверки назначений и достижимости.
  6. desugar: перезаписывает AST и переводит немного синтаксического сахара.
  7. generate: генерирует исходные файлы или файлы классов.

Более подробно:

  1. Lex - разбить исходный файл на отдельные слова или токены.
  2. Разбор - Проанализируйте словосочетание программы.
  3. Семантические действия. Создайте фрагмент абстрактного синтаксического дерева, соответствующего каждой фразе.
  4. Семантический анализ - определите, что означает каждая фраза, свяжите использование переменных с их определениями, проверьте типы выражений, запросите перевод каждой фразы.
  5. Структура кадра - размещение переменных, параметров функции и т. Д. В записи активации (стековые кадры) машинно-зависимым способом.
  6. Перевести - создать промежуточные деревья представления (IR-деревья), нотацию, которая не привязана к какому-либо конкретному исходному языку или архитектуре целевой машины.
  7. Canonicalize - поднимает побочные эффекты из выражений и очищает условные переходы для удобства следующих этапов.
  8. Выбор инструкций - сгруппируйте узлы IR-дерева в комки, которые соответствуют действиям инструкций целевой машины.
  9. Анализ потока управления - проанализируйте последовательность инструкций в графике потока управления, который показывает все возможные потоки управления, которым может следовать программа, когда она выполняется.

  10. Анализ потока данных - сбор информации о потоке информации через переменные программы; например, анализ живучести вычисляет места, где каждая программная переменная содержит все еще необходимое значение (является живым).

  11. Распределение регистра - выберите регистр для хранения каждой из переменных и временных значений, используемых программой; переменные, которые не живут одновременно, могут использовать один и тот же регистр.

  12. Эмиссия кода - замените временные имена в каждой машинной инструкции на машинные регистры.

Есть хорошая книга:

Современная реализация компилятора на Java

Вы можете заглянуть внутрь кода Javac:

Документация по Javac

OpenJDK исходный код

Руководство хакера по javac

Не паникуйте! Чтобы помочь новичкам в работе с javac, они могут перемещаться по базе кода.

JVM JLS

В компиляторе есть разные шаги, но вот самые важные:

Лексический анализ Первый шаг - это лексический анализ. В основном эти шаги извлекают токены из кода Java (ключевые слова, операторы, разделители, комментарии, имена переменных...)

Синтаксический анализ (синтаксический анализатор) Вторым шагом является синтаксический анализ. Токены взяты из лексического анализа и объединены в выражения и инструкции.

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


Примечание. Этот процесс относится не только к Java, но и является общим для всех компиляторов. Также компиляторы, которые генерируют не промежуточный байтовый код, а машинный код (например, компиляторы для C или C++).

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

Гибкий лексический анализатор с открытым исходным кодом. Полезный синтаксический анализатор - yacc.

Оба работают с C и C++, которые являются наиболее используемыми языками для создания компиляторов (также java и другие), но есть и аналогичные альтернативы для других языков программирования (для создания компилятора на другом языке, а не на другом языке). В основном язык, на котором написан компилятор, не связан с языком, который компилирует компилятор.

Другие вопросы по тегам