Как именно происходит компиляция Java? - PullRequest
57 голосов
/ 04 августа 2010

Смущает процесс компиляции Java

ОК, я знаю это: мы пишем исходный код java, компилятор, который не зависит от платформы, переводит его в байт-код, затем jvm, который зависит от платформы, переводит его в машинный код.

Итак, с самого начала мы пишем исходный код Java. Компилятор javac.exe представляет собой файл .exe. Что именно это файл .exe? Разве java-компилятор не написан на java, тогда как получается .exe-файл, который его выполняет? Если код компилятора написан на java, то почему код компилятора выполняется на этапе компиляции, так как это задача jvm - выполнить код java. Как сам язык может компилировать свой собственный код языка? Мне кажется, что это проблема с курицей и яйцом.

Теперь, что именно содержит файл .class? Это абстрактное синтаксическое дерево в текстовом виде, табличная информация, что это?

Кто-нибудь может рассказать мне ясный и подробный способ преобразования моего исходного кода Java в машинный код.

Ответы [ 9 ]

58 голосов
/ 04 августа 2010

ОК, я знаю это: мы пишем исходный код Java, компилятор, который не зависит от платформы, переводит его в байт-код,

На самом деле сам компилятор работает как собственный исполняемый файл (отсюда и javac.exe). И правда, он преобразует исходный файл в байт-код. Байт-код не зависит от платформы, поскольку он нацелен на виртуальную машину Java.

затем jvm, который зависит от платформы, переводит его в машинный код.

Не всегда. Что касается JVM от Sun, то здесь есть два jvms: клиент и сервер. Они оба могут, но не обязательно должны компилироваться в нативный код.

Итак, с самого начала мы пишем исходный код Java. Компилятор javac.exe представляет собой файл .exe. Что именно это файл .exe? Разве Java-компилятор не написан на Java, тогда как получается .exe-файл, который его выполняет?

Этот exe файл представляет собой упакованный байт-код Java. Это для удобства - чтобы избежать сложных пакетных скриптов. Он запускает JVM и запускает компилятор.

Если код компилятора написан на java, то почему код компилятора выполняется на этапе компиляции, так как его задача jvm - выполнять код java.

Это именно то, что делает код переноса.

Как сам язык может компилировать свой собственный код языка? Мне кажется, что это проблема с курицей и яйцом.

Правда, сбивает с толку на первый взгляд. Хотя это не только идиома Java. Компилятор Ады также написан на самой Аде. Это может выглядеть как «проблема с курицей и яйцом», но на самом деле это только проблема начальной загрузки.

Теперь, что именно содержит файл .class? Это абстрактное синтаксическое дерево в текстовой форме, табличная информация, что это?

Это не абстрактное синтаксическое дерево. AST используется токенизатором и компилятором только во время компиляции для представления кода в памяти. Файл .class похож на сборку, но для JVM. JVM, в свою очередь, является абстрактной машиной, которая может работать на специализированном машинном языке - ориентированной только на виртуальную машину. В простейшем случае, .class файл имеет структуру, очень похожую на обычную сборку. Сначала объявляются все статические переменные, затем идут несколько таблиц сигнатур внешних функций и, наконец, машинный код.

Если вам действительно любопытно, вы можете покопаться в файле классов, используя утилиту "javap". Вот примерный (запутанный) результат вызова javap -c Main:

0:   new #2; //class SomeObject
3:   dup
4:   invokespecial   #3; //Method SomeObject."<init>":()V
7:   astore_1
8:   aload_1
9:   invokevirtual   #4; //Method SomeObject.doSomething:()V
12:  return

Итак, вы должны уже иметь представление о том, что это на самом деле.

Кто-нибудь может рассказать мне ясный и подробный способ преобразования моего исходного кода Java в машинный код.

Я думаю, что сейчас это должно быть более понятно, но вот краткое резюме:

  • Вы вызываете javac, указывая на файл исходного кода. Внутренний ридер (или токенизатор) javac считывает ваш файл и создает из него реальный AST. Все синтаксические ошибки происходят с этой стадии.

  • javac еще не закончил свою работу. Когда у него есть AST, может начаться истинная компиляция. Он использует шаблон посетителя для обхода AST и разрешает внешние зависимости, чтобы добавить смысл (семантику) в код. Готовый продукт сохраняется в виде .class файла, содержащего байт-код.

  • Теперь пришло время запустить вещь. Вы вызываете java с именем .classfile. Теперь JVM запускается снова, но интерпретирует Ваш код. JVM может или не может скомпилировать Ваш абстрактный байт-код в собственную сборку. Компилятор Sun HotSpot в сочетании с компиляцией Just In Time может сделать это при необходимости. Выполняемый код постоянно профилируется JVM и перекомпилируется в собственный код, если соблюдаются определенные правила. Чаще всего код hot компилируется первым.

Edit: без javac нужно было бы вызвать компилятор, используя что-то похожее на это:

%JDK_HOME%/bin/java.exe -cp:myclasspath com.sun.tools.javac.Main fileToCompile

Как вы можете видеть, он вызывает частный API Sun, поэтому он связан с реализацией Sun JDK.Это сделало бы системы сборки зависимыми от него.Если кто-то переключился на любой другой JDK (вики-списки 5, кроме Sun), приведенный выше код следует обновить, чтобы отразить это изменение (поскольку маловероятно, что компилятор будет находиться в пакете com.sun.tools.javac).Другие компиляторы могут быть написаны на нативном коде.

Поэтому стандартным способом является поставка javac оболочки с JDK.

15 голосов
/ 04 августа 2010

Разве java-компилятор не написан на java, тогда как получается .exe-файл, который его выполняет?

Откуда вы получаете эту информацию?Исполняемый файл javac может быть написан на любом языке программирования, он не имеет значения, все, что важно, это то, что это исполняемый файл, который превращает .java файлы в .class файлы.

Подробнее о двоичном файлеспецификацию файла .class вы можете найти в этих главах в Java Language Specification , полезной (хотя, возможно, немного технической):

Вы также можете взглянуть на Спецификацию виртуальной машины , которая охватывает:

11 голосов
/ 04 августа 2010

Компилятор javac.exe представляет собой файл .exe. Что именно это файл .exe? не компилятор Java, написанный на Java, тогда как же .exe файл, который выполняет это?

Компилятор Java (по крайней мере, тот, который поставляется с JDK Sun / Oracle) действительно написан на Java. javac.exe - это просто средство запуска, которое обрабатывает аргументы командной строки, некоторые из которых передаются JVM, которая запускает компилятор, а другие - самому компилятору.

Если написан код компилятора Java, тогда почему код компилятора выполнено на этапе компиляции, так как это работа JVM в выполнить код Java. Как язык сам компилировать свой код языка? Все это похоже на курицу и яйцо проблема для меня.

Многие (если не большинство) компиляторы написаны на языке, который они компилируют. Очевидно, на каком-то раннем этапе сам компилятор должен был быть скомпилирован чем-то другим, но после этой «начальной загрузки» любая новая версия компилятора может быть скомпилирована более старой версией.

Теперь, что именно делает файл .class содержат? Это абстрактное синтаксическое дерево в текстовом виде, это табличное информация, что это?

Подробности формата файла класса описаны в спецификации виртуальной машины Java .

5 голосов
/ 04 августа 2010

Ну, javac и jvm обычно являются родными двоичными файлами.Они написаны на С или как угодно.Конечно, можно написать их на Java, просто сначала вам нужна нативная версия.Это называется «загрузкой».

Интересный факт: большинство компиляторов, которые компилируются в нативный код, написаны на своем собственном языке.Однако им всем сначала нужно было написать нативную версию на другом языке (обычно C).Первый компилятор C, для сравнения, был написан на Ассемблере.Я предполагаю, что первый ассемблер был написан в машинном коде.(Или с использованием бабочек ;)

.class файлы - это байт-код, сгенерированный javac.Они не текстовые, они представляют собой двоичный код, похожий на машинный код (но с другим набором команд и архитектурой).

Во время выполнения у jvm есть два варианта: он может интерпретировать байткод (притворяясь самим процессором), или он может JIT (точно в срок) скомпилировать его в машинный код.Последнее, конечно, быстрее, но сложнее.

3 голосов
/ 04 августа 2010

Файл .class содержит байт-код, который вроде , как очень сборка высокого уровня .Компилятор вполне может быть написан на Java, но JVM придется компилировать в нативный код, чтобы избежать проблемы "курица / яйцо".Я считаю, что он написан на C, как и нижние уровни стандартных библиотек.Когда JVM запускается, он выполняет своевременную компиляцию, чтобы превратить этот байт-код в собственные инструкции.

2 голосов
/ 13 мая 2016

Краткое объяснение

Напишите код в текстовом редакторе, сохраните его в формате, понятном компилятору - ". Java" расширение файла, javac (компилятор java) преобразует это в " .class " файл формата (байт-код - файл класса). JVM выполняет файл .class в операционной системе, в которой он находится.

Длинное объяснение

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

Каждый компьютерный процесс занимается манипуляциями с памятью. Мы не можем просто написать код в текстовом редакторе и скомпилировать его. Нам нужно поместить его в память компьютера, т.е. сохранить его перед компиляцией.

Как javac (компилятор java) распознает сохраненный текст как компилируемый? - У нас есть отдельный текстовый формат, который распознает компилятор, т. Е. .java . Сохраните файл с расширением .java, и компилятор распознает его и скомпилирует по запросу.

Что происходит при компиляции? - Компилятор - это второй переводчик (не технический термин), участвующий в процессе, он переводит понятный пользователю язык (java) на понятный JVM язык (байт-код - формат .class).

Что происходит после компиляции? - Компилятор создает файл .class, который понимает JVM. Затем программа выполняется, то есть файл .class выполняется JVM в операционной системе.

Факты, которые вы должны знать

1) Java не мультиплатформенная она независимая от платформы .

2) JVM разработана с использованием C / C ++ . Одна из причин, почему люди называют Java более медленным языком, чем C / C ++

3) Байт-код Java (.class) находится на «языке ассемблера» , единственном языке, понятном для JVM. Любой код, который создает файл .class при компиляции или сгенерированный байт-код, можно запустить на JVM.

1 голос
/ 04 августа 2010

Windows не знает, как вызывать программы Java перед установкой среды выполнения Java, и Sun решила иметь собственные команды, которые собирают аргументы и затем вызывают JVM вместо привязки суффикса jar к движку Java.

0 голосов
/ 28 мая 2014
  1. .java файл
  2. компилятор (JAVA BUILD)
  3. .class (байт-код)
  4. JVM (системное программное обеспечение обычно создается с использованием C)
  5. РАБОЧАЯ ПЛАТФОРМА
  6. ПРОЦЕССОР
0 голосов
/ 04 августа 2010

Компилятор изначально был написан на C с битами C ++, и я предполагаю, что он все еще есть (как вы думаете, почему компилятор также написан на Java?). javac.exe - это просто код C / C ++, являющийся компилятором.

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

Файл .class содержит байт-коды, выходные данные процесса компиляции javac, и это инструкции, которые говорят JVM, что делать. Во время выполнения эти байт-коды транслируются в собственные инструкции процессора (машинный код), чтобы они могли выполняться на конкретном оборудовании в рамках JVM.

Чтобы немного усложнить это, JVM также оптимизирует и кэширует машинный код, полученный из байт-кодов, чтобы избежать их многократного перевода. Это называется JIT-компиляцией и происходит во время работы программы и интерпретации байт-кодов.

...