Внутренняя архитектура компилятора Java
Я работал над Java
с более чем 8 лет.
На прошлой неделе на небольшом собрании в моей компании один из моих коллег спросил меня, как именно Java Compiler
Работа? Я был без ответа.
Я попытался объяснить, как Java Compiler принимает операторы один за другим и преобразует их в байтовый код, который не предназначен ни для каких OS
но JVM
,
Никто не удовлетворен этим ответом, даже я.
Теперь главный вопрос - как именно работает компилятор Java. т.е. сколько шагов или этапов или фаз есть, что будет сделано компилятором в случае компиляции Java
файл.
Что именно Java's compiler
архитектура?
Что делать, если есть несколько Java classes
в том же файле.java. Тогда сколько классов будет скомпилировано.
Что делать, если есть импорт, указывающий на не скомпилированные классы Java? Тогда некомпилированные классы будут скомпилированы или проигнорированы?
Я гуглил больше половины дня, и все дают тот же ответ, что и моим коллегам.
Но, наконец, я нашел здесь полезное руководство.
Но учебник также охватывал не слишком углубленно, и я не смог визуализировать этот учебник.
Тем не менее, я не удовлетворен и не хочу узнать что-то еще об этом от вас.
Так что, если кто-то знает что-то большее, чем я и вышеупомянутый блог, что-то, с помощью которого я могу визуализировать, что именно внутренняя архитектура Java Compiler
пожалуйста, объясните мне.
2 ответа
Некоторые основные шаги:
- parse: читает набор исходных файлов *.java и отображает полученную последовательность токенов в узлы AST (абстрактное синтаксическое дерево).
- enter: ввод символов для определений в таблицу символов.
- Обрабатывать аннотации: если требуется, обрабатывает аннотации, найденные в указанных единицах компиляции.
- Атрибут: Атрибуты деревьев синтаксиса. Этот шаг включает в себя разрешение имен, проверку типов и постоянное свертывание.
- flow: выполняет анализ потока данных на деревьях из предыдущего шага. Это включает в себя проверки назначений и достижимости.
- desugar: перезаписывает AST и переводит немного синтаксического сахара.
- generate: генерирует исходные файлы или файлы классов.
Более подробно:
- Lex - разбить исходный файл на отдельные слова или токены.
- Разбор - Проанализируйте словосочетание программы.
- Семантические действия. Создайте фрагмент абстрактного синтаксического дерева, соответствующего каждой фразе.
- Семантический анализ - определите, что означает каждая фраза, свяжите использование переменных с их определениями, проверьте типы выражений, запросите перевод каждой фразы.
- Структура кадра - размещение переменных, параметров функции и т. Д. В записи активации (стековые кадры) машинно-зависимым способом.
- Перевести - создать промежуточные деревья представления (IR-деревья), нотацию, которая не привязана к какому-либо конкретному исходному языку или архитектуре целевой машины.
- Canonicalize - поднимает побочные эффекты из выражений и очищает условные переходы для удобства следующих этапов.
- Выбор инструкций - сгруппируйте узлы IR-дерева в комки, которые соответствуют действиям инструкций целевой машины.
Анализ потока управления - проанализируйте последовательность инструкций в графике потока управления, который показывает все возможные потоки управления, которым может следовать программа, когда она выполняется.
Анализ потока данных - сбор информации о потоке информации через переменные программы; например, анализ живучести вычисляет места, где каждая программная переменная содержит все еще необходимое значение (является живым).
Распределение регистра - выберите регистр для хранения каждой из переменных и временных значений, используемых программой; переменные, которые не живут одновременно, могут использовать один и тот же регистр.
Эмиссия кода - замените временные имена в каждой машинной инструкции на машинные регистры.
Есть хорошая книга:
Современная реализация компилятора на Java
Вы можете заглянуть внутрь кода Javac:
Не паникуйте! Чтобы помочь новичкам в работе с javac, они могут перемещаться по базе кода.
В компиляторе есть разные шаги, но вот самые важные:
Лексический анализ Первый шаг - это лексический анализ. В основном эти шаги извлекают токены из кода Java (ключевые слова, операторы, разделители, комментарии, имена переменных...)
Синтаксический анализ (синтаксический анализатор) Вторым шагом является синтаксический анализ. Токены взяты из лексического анализа и объединены в выражения и инструкции.
Оптимизация и преобразование в байт-код Последний шаг макроса - преобразование предыдущего шага в байт-код. Здесь код может быть изменен, чтобы быть эквивалентным исходному коду, но более эффективным.
Примечание. Этот процесс относится не только к Java, но и является общим для всех компиляторов. Также компиляторы, которые генерируют не промежуточный байтовый код, а машинный код (например, компиляторы для C или C++).
Как правило, существуют инструменты для создания лексического анализатора и синтаксического анализатора, потому что в этих шагах есть много общих частей между различными языками.
Гибкий лексический анализатор с открытым исходным кодом. Полезный синтаксический анализатор - yacc.
Оба работают с C и C++, которые являются наиболее используемыми языками для создания компиляторов (также java и другие), но есть и аналогичные альтернативы для других языков программирования (для создания компилятора на другом языке, а не на другом языке). В основном язык, на котором написан компилятор, не связан с языком, который компилирует компилятор.