Является ли Java компилируемым или интерпретируемым языком программирования?

169

В прошлом я использовал C ++ в качестве языка программирования. Я знаю, что код, написанный на C ++, проходит процесс компиляции, пока не станет объектным кодом «машинный код».

Я хотел бы знать, как Java работает в этом отношении. Как пользовательский Java-код запускается компьютером?

отображаемое имя
источник
14
C ++ можно интерпретировать. Там есть несколько интерпретаторов Си.
Том Хотин - tackline

Ответы:

220

Реализации Java обычно используют двухэтапный процесс компиляции. Исходный код Java компилируется в байт-код компилятором Java. Байт-код выполняется виртуальной машиной Java (JVM). Современные JVM используют метод компиляции Just-in-Time (JIT) для компиляции байт-кода с нативными инструкциями, понятными аппаратному ЦП на лету во время выполнения.

Некоторые реализации JVM могут интерпретировать байт-код вместо JIT, компилируя его в машинный код и выполняя его напрямую. Хотя это все еще считается «интерпретатором», он довольно сильно отличается от интерпретаторов, которые читают и выполняют исходный код высокого уровня (то есть в этом случае исходный код Java не интерпретируется напрямую, это байт-код, вывод компилятора Java).

Технически возможно заблаговременно скомпилировать Java в нативный код и запустить полученный бинарный файл. Также возможно интерпретировать код Java напрямую.

Подводя итог, в зависимости от среды выполнения, байт-код может быть:

  • заблаговременно скомпилировано и выполнено как собственный код (аналогично большинству компиляторов C ++)
  • скомпилировано точно в срок и выполнено
  • интерпретированы
  • выполняется непосредственно поддерживаемым процессором (байт-код является собственным набором команд некоторых процессоров)
Мехрдад Афшари
источник
20
Фактически, некоторые JVM HotSpot начинают с интерпретации байт-кодов и компилируют их в собственный код только после того, как они выяснили, что стоит компилировать, и собрали некоторые статистические данные о том, как выполняется код; например, чтобы выяснить наиболее распространенный путь в каждой условной ветви.
Стивен С
1
Отсюда и термин «горячая точка» :) Это делает то, что часто выполняется, чтобы получить оптимизацию.
Шелковый полдень
4
Вы можете отключить переводчик в HotSpot с помощью -Xcomp. Стоит попробовать приложение, чтобы увидеть, что это за плохая идея.
Том Хотин - tackline
1
Существует утверждение: «Текущая версия Sun HotSpot JVM использует метод компиляции Just-in-time (JIT) для компиляции байт-кода с собственными инструкциями, понятными ЦП на лету во время выполнения». У меня сложилось впечатление, что JVM - это интерпретатор, но он предполагает дальнейшую компиляцию байтового кода. Я смущен. Также написано, что он делает это на лету во время выполнения. Может кто-нибудь объяснить это тоже?
Ананд
Поскольку Java является интерпретируемым языком, как это повлияет на производительность или выполнение любого Java-приложения
NAND
94

введите описание изображения здесь

Код, написанный на Java:

  • Сначала скомпилированный в байт-код программой javac, как показано в левой части изображения выше;
  • Затем, как показано в правой части изображения выше, другая программа называется Java запускает среду выполнения Java и может компилировать и / или интерпретировать байт-код с помощью Java Interpreter / JIT Compiler.

Когда Java интерпретирует байт-код и когда он его компилирует? Код приложения первоначально интерпретируется, но JVM отслеживает, какие последовательности байт-кода часто выполняются, и транслирует их в машинный код для непосредственного выполнения на оборудовании. Для байт-кода, который выполняется только несколько раз, это экономит время компиляции и уменьшает начальную задержку; для часто выполняемого байт-кода JIT-компиляция используется для запуска на высокой скорости после начальной фазы медленной интерпретации. Кроме того, поскольку программа тратит большую часть времени на выполнение меньшего количества кода, сокращение времени компиляции является значительным. Наконец, во время первоначальной интерпретации кода, статистика выполнения может быть собрана до компиляции, что помогает выполнять лучшую оптимизацию.

отображаемое имя
источник
Из-за кэшированного байт-кода Java использует много памяти?
Педро Гордо
3
@sedulam: «много памяти» - нечеткое утверждение. Управление памятью в Java довольно простое - три поколения - это то, что JVM использует для создания и обслуживания своих объектов. Этот другой SO ответ может быть полезным для вас.
displayName
С вышеприведенным объяснением теоретически скомпилированный код C ++ всегда должен быть быстрее, чем логически подобный Java-код, поскольку всегда будет некоторая часть файла .class, которую JIT решит не преобразовывать в машинный код. Другими словами, java никогда не сможет поймать скорость исполнения без использования железа, которую продемонстрировал C ++. Это правильное предположение?
DevdattaK
@DevdattaK: Я не слишком много знаю C ++, но я предполагаю , что для небольших и специализированных программ Java может дать вам результат быстрее, потому что не будет тратить время на компиляцию тех частей кода, где не так много ускорения.
displayName
1
@DevdattaK Ваше предположение обсуждается на этой вики-странице en.m.wikipedia.org/wiki/Java_performance?wprov=sfla1 Короче говоря, это не всегда так.
Сундар Раджан
59

Термины «интерпретируемый язык» или «скомпилированный язык» не имеют смысла, потому что любой язык программирования может интерпретироваться и / или компилироваться.

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

В настоящее время частичная компиляция точно в срок используется для многих языков, которые когда-то считались «интерпретированными», например JavaScript.

starblue
источник
5
Кроме того, Google V8 JavaScript Execution Engine не просто выполняет частичную своевременную компиляцию. Он всегда компилируется в нативный код, фактически в V8 даже нет интерпретатора. Он имеет только компилятор (похож на Maxine, но в отличие от Maxine V8 имеет только один компилятор). Все три из этих примеров (GCJ, Maxine и V8) подтверждают вашу точку зрения еще сильнее: не существует такого понятия, как интерпретируемый язык или скомпилированный язык. Язык не интерпретируется и не компилируется. Язык просто есть (это на самом деле цитата Шрирама Кришнамурти).
Йорг Миттаг
3
Почему вы говорите о JavaScript в вопросе Java?
Корай Тугай
1
@KorayTugay Просто в качестве примера. Я, конечно, не хочу подразумевать, что у Java и Javascript есть что-то общее, кроме первых четырех букв их имени.
StarBlue
Разве, по крайней мере, разница в интерпретируемом и скомпилированном языке не означает, что двоичный файл скомпилированного языка не может изменить свой поток выполнения в любое время, в то время как интерпретируемый язык очень послушен некоторым из текущих функций функций? Библиотеки в C это опция, в то время как в других языках вы не можете иметь объект массива без двоичного расширения C, которое может быть обновлено или может быть совершенно другим кодом на другой платформе. Язык сценариев сможет работать на обоих, в то время как скомпилированный язык будет нуждаться в другом бинарном файле
Eaton Emmerich
53

Java компилируется в байт-код, который затем переходит в Java VM, которая его интерпретирует.

Шелковый полдень
источник
33
... но не совсем точно.
Стивен С
2
JVM может предпочесть не «интерпретировать» байт-код. Он может JIT скомпилировать и выполнить его напрямую.
Мердад Афшари
1
Технически JIT не выполняет его напрямую. Я просто вспоминаю, как это было выполнено.
Клет
Mehrdad: Согласен, я не описывал возможные операции JIT здесь, так как считаю это до JVM, и я все равно оставляю свой ответ простым :)
Noon Silk
7
Клетус: После JIT это будет выполнено напрямую. JIT читает фрагмент байт-кода (например, полный метод), компилирует его в машинный код и переходит к нему.
Мердад Афшари
12

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

Сэм Харвелл
источник
11

Вид обоих. Сначала компилируется Java (некоторые предпочитают говорить «переведенный») в байт-код, который затем либо компилируется, либо интерпретируется в зависимости от настроения JIT.

maykeye
источник
32
Это продвинутая часть программного обеспечения, чтобы развить настроение :)
Thorarin
5
JIT - действительно очень сложная часть программного обеспечения, которая может выполнять оптимизацию на основе информации времени выполнения (например, профилировщика), чего не может сделать преждевременный компилятор (потому что у него нет информации о поведении времени выполнения программа заранее). Но у этого, вероятно, действительно нет настроений ... :-)
Джеспер
5

Java выполняет как компиляцию, так и интерпретацию,

В Java программы не компилируются в исполняемые файлы ; они компилируются в байт-код (как обсуждалось ранее), который JVM (виртуальная машина Java) затем интерпретирует / выполняет во время выполнения. Исходный код Java компилируется в байт-код, когда мы используем компилятор javac. Байт-код сохраняется на диске с расширением .class .

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

Javac - это компилятор Java который компилирует код Java в байт-код. JVM - это виртуальная машина Java, которая выполняет / интерпретирует / переводит байт-код в машинный код. В Java, хотя он считается интерпретируемым языком, он может использовать компиляцию JIT (Just-in-Time), когда байт-код находится в JVM. JIT-компилятор считывает байт-коды во многих разделах (или полностью, редко) и динамически компилирует их в машинный код, чтобы программа могла работать быстрее, а затем кэшироваться и повторно использоваться позже без необходимости перекомпиляции. Таким образом, JIT-компиляция сочетает в себе скорость скомпилированного кода с гибкостью интерпретации.

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

Компилируемый язык является языком программирования , чьи реализации , как правило , составители (переводчики , которые генерируют машинный код из исходного кода), а не переводчики (шаг за шагом исполнителями исходного кода, где нет предварительного выполнения перевода не происходит)

В современных реализациях на языке программирования, таких как в Java, для платформы все более популярно предоставлять обе опции.

простое число
источник
Должно быть «байт - код может быть преобразован» , а не « это преобразованное». Спецификации Java определяют байт-код. Независимо от того, выполняется ли этот байт-код (a) непосредственно в аппаратном обеспечении , (b) через интерпретатор, (c) скомпилирован заранее или (d) частично скомпилирован на лету во время выполнения , все оставлено в качестве подробностей реализации. Обратите внимание, что все четыре из этих опций действительно использовались различными реальными реализациями Java.
Василий Бурк
Спасибо за указание на это. Так что же произойдет, если байт-код не будет преобразован в машинный код? Я могу вспомнить сценарий, в котором байт-код является набором собственных команд для некоторых процессоров, и тогда нет необходимости в преобразовании. Или я что-то упустил.
премьер
Нажмите на ссылку, которую я дал для технологии Jazelle DBX (Direct Bytecode eXecution) , где подмножество байт-кода JVM - это машинные инструкции собственного процессора (своего рода сортировка). Без этого вы получаете машинный код, сгенерированный из байт-кода (a) от интерпретатора (на лету), (b) от компилятора заранее или (c) на лету с помощью компилятора, работающего точно в срок ( сначала интерпретируется, а затем иногда компилируется и кэшируется во время выполнения).
Василий Бурк
-2

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

Hobbs
источник
1
Что означает «байтово скомпилированный»?
Джеспер
2
@Jesper: «Byte-compiled» обычно означает «скомпилированный в байт-код». «Байт-код» - это общий термин, охватывающий любой нетекстовый промежуточный код (обычно не исполняемый на компьютере).
Грег Хьюгилл
-3

Цитата из: https://blogs.oracle.com/ask-arun/entry/run_your_java_applications_faster

Разработчики приложений могут разрабатывать код приложения для любой из различных ОС, доступных на рынке сегодня. На данном этапе язык Java не зависит от ОС. Блестящий исходный код, написанный разработчиком Java-приложения, теперь компилируется в байт-код Java, который в терминологии Java называется компиляцией на стороне клиента. Эта компиляция в Java-байт-код позволяет разработчикам Java «писать один раз». Байт-код Java может работать на любой совместимой ОС и сервере, что делает независимый исходный код ОС / Сервера. После создания байтового кода Java взаимодействие между Java-приложением и базовой ОС / сервером более тесное. Путешествие продолжается - платформа корпоративных приложений выполняет эти байтовые коды Java в среде выполнения, известной как виртуальная машина Java (JVM) или среда выполнения Java (JRE). JVM имеет тесные связи с базовой ОС и оборудованием, поскольку использует ресурсы, предлагаемые ОС и сервером. Байт-код Java теперь компилируется в исполняемый код машинного языка, который зависит от платформы. Это называется компиляцией на стороне сервера.

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

Teo
источник