Компиляция против перевода, компиляция Java в байт-код?

Мое понимание таково, определения:

Перевод — наличие кода на одном языке, создание кода на другом языке.

Compilaton — перевод в машинный код.

Машинный код — прямые инструкции для процессора.

Теперь из docs.oracle.com:

javac — язык программирования Java компилятор

Компилятор...? Я думаю, что это переводчик Java, потому что он генерирует код, который не является машинным кодом. Для запуска байт-кода требуется интерпретатор (JVM), поэтому он определенно не является машинным кодом.

Из Википедии:

Приложения Java обычно компилируются в байт-код.

Сходным образом. Согласно определениям, я бы сказал, что Java переводится в байт-код. В Интернете есть еще много примеров, я думаю, что это путаница, или я просто что-то упускаю.

Не могли бы вы уточнить это? В чем разница между переводом и компиляцией?


person Adam Stelmaszczyk    schedule 18.05.2013    source источник
comment
Ваши определения неверны.   -  person SK-logic    schedule 21.05.2013


Ответы (4)


Все дело в определениях, и не существует единого общепринятого определения того, что означает "компиляция". В ваших глазах компиляция — это преобразование исходного кода на каком-то языке в нативный; поэтому процесс преобразования, который не генерирует машинный код, не должен называться «компиляцией». В моих глазах (и, видимо, в глазах javac авторов документации) так и должно быть.

На самом деле существует множество различных терминов: перевод, компиляция, декомпиляция, сборка, дизассемблирование и так далее.

Лично я бы сказал, что имеет смысл сгруппировать все эти термины под словом «компиляция», потому что все эти процессы имеют много общего:

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

Кроме того, ваше определение «производит собственный код» проблематично:

  • Как насчет компиляторов, которые могут генерировать ассемблер, но не утруждают себя преобразованием его в машинный код, оставляя это внешней программе (обычно называемой «ассемблером»)? Вы бы отказали им в этом определении «компиляторов» из-за этого последнего, незначительного в сравнении шага?
  • Как вы вообще классифицируете «машинный код»? Что, если завтра будет создан процессор, способный запускать Java Bytecode?

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

  • Компиляция — это преобразование кода на языке более высокого уровня в код более низкого уровня. Примеры: Java в байт-код Java или машинный код C в x86.
  • Декомпиляция — это преобразование кода на языке более низкого уровня в код более высокого уровня, что, по сути, противоположно компиляции. Примеры: байт-код Java в Java.
  • Перевод или компиляция исходного кода — это преобразование кода на каком-либо языке в другой язык сопоставимого «уровня». Примеры: с ARM на x86 или с C на Java. Когда два языка на самом деле являются разными версиями одного и того же языка (например, Javascript 6 — Javascript 5), также используется термин транспилятор.
  • Assembly — это преобразование кода на каком-либо языке ассемблера в машинный код.
  • Дизассемблирование — это либо синоним декомпиляции, либо противоположность сборке, в зависимости от контекста.

Согласно этим определениям, javac определенно можно рассматривать как компилятор. Но опять же, все дело в определениях: с технической точки зрения многие из этих действий имеют много общего.

person Oak    schedule 18.05.2013

Результатом javac является машинный код. Тот факт, что машина является виртуальной, а не физической, не имеет значения (иначе вы могли бы утверждать, что компиляция кода в x86 была переводом, если бы вы были пользователем Mac, поскольку код x86 не является машинным кодом Mac).

person SJuan76    schedule 18.05.2013
comment
С 2006 года Mac используют платформу x86. - person Mark Rotteveel; 18.05.2013
comment
Почему бы не перевести с C++ на x86, а затем скомпилировать с x86 на машинный код PowerPC? Я думаю, что лучше поставить байт-код == машинный код. Как машинный код x86 может быть в том же классе, что и байт-код... - person Adam Stelmaszczyk; 18.05.2013
comment
Нет такого языка, как x86. Вы можете перевести C++ на машинный язык, но его все равно нужно будет скомпилировать в машинный код. Язык — это текст, основанный на человеке-разработчике, и он абстрагирован от реальной машины. Машинный код — это то, что может запустить ЦП. - person Peter Lawrey; 18.05.2013
comment
Я думаю, у нас разные определения языка. Я думаю, что язык не обязательно должен быть основан на тексте. Язык оперирует символами. 01 или текст (или голоса), не имеет значения. Человек также может читать инструкции 01. - person Adam Stelmaszczyk; 18.05.2013
comment
Затем, согласно этому определению, все является языком, который вы никогда не компилируете и всегда переводите. Бесполезное определение, если оно служит всем. - person SJuan76; 18.05.2013
comment
Нет, вы компилируете, если вы переводите в машинный код (который является языком по символическому определению). - person Adam Stelmaszczyk; 18.05.2013
comment
Более полезно поставить байт-код == машинный код? А если у нас 5 виртуальных машин? На абстрактном первом мы пишем код, который транслируется на второй, менее абстрактный, и так далее... То есть мы должны говорить скомпилированный, а не переведенный? Я думаю, это более запутанно. Последним переводом в этой модели с 5 виртуальными машинами будет компиляция (в соответствии с определениями, которые я дал). - person Adam Stelmaszczyk; 18.05.2013
comment
С вашим определением вы будете 5 раз (всегда) компилировать, никогда не переводить. - person Adam Stelmaszczyk; 18.05.2013
comment
Знаете, я с вами не спорю, я учусь, пытаюсь понять это :) Вы более опытны, чем я, поэтому, если мое определение, например, языка неверно (т.е. большинство людей понимает его как-то вы мне сказали) - это нормально :) Но я слышал это символическое определение и с ним вроде все нормально работает. Так что мне просто любопытно, может быть, это как наследие? Некоторое время назад кто-то просто назвал его javac, и со временем все просто привыкли к нему, получили определения, которые будут придерживаться компиляции java в байт-код и т. д. - person Adam Stelmaszczyk; 18.05.2013

«Компилятор — это компьютерная программа (или набор программ), которая преобразует исходный код, написанный на языке программирования (исходном языке), в другой компьютерный язык (целевой язык, часто имеющий двоичную форму, известную как объектный код)».

http://en.wikipedia.org/wiki/Compiler

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

Теперь я знаю, по крайней мере, компилятор NesC, который выполняет ту же процедуру.

Можно построить машину, которая запускает байт-код JVM, на самом деле в некоторых главах «Структурированная компьютерная организация» А. Таненбаума описывается, как это сделать.

https://rads.stackoverflow.com/amzn/click/com/0131485210

person LtWorf    schedule 18.05.2013
comment
Компиляция == перевод? Так что, вместо этого все переводчики должны называться компиляторами? - person Adam Stelmaszczyk; 18.05.2013
comment
Перевод более общий, я мог бы перевести с английского на испанский, и я бы не назвал это компиляцией, но в области компьютерных языков да, безусловно. - person LtWorf; 18.05.2013

Компилятор...? Я думаю, что это транслятор Java, потому что он генерирует код, который не является машинным кодом. Для запуска байт-кода требуется интерпретатор (JVM), поэтому он определенно не является машинным кодом.

JVM — это Виртуальная машина Java, которая представляет собой машину, а ее машинный код называется байт-кодом Java. (Каждый «байт» в байтовом коде является машинной инструкцией JVM.)

Вы можете узнать больше, прочитав спецификацию JVM. Начните здесь: https://docs.oracle.com/javase/specs/

Кроме того, JVM не является интерпретатором; это определение машины. Некоторые реализации JVM включают JIT-компиляторы, опережающие компиляторы (AOT), адаптивные компиляторы (например, Hotspot) и, да, даже интерпретаторы (хотя я не я лично не видел интерпретатор Java за последние 20 лет).

Большинство людей, начинающих заниматься компиляторами, не понимают, что больше нет компиляторов, которые генерируют «машинный код». Все они генерируют некоторые промежуточные формы (как определено, например, конкретной ОС), которые затем загружаются и обрабатываются ОС.

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

В настоящее время даже C не компилирует код в настоящие машинные исполняемые файлы без раскрашивания за пределами строк. (Напишите настоящий работающий загрузчик с нуля и вернитесь ко мне.)

person cpurdy    schedule 14.04.2018