Java «Виртуальная машина» или язык интерпретатора Python?

207

Кажется редким читать Python о «виртуальной машине», в то время как в Java «виртуальная машина» используется постоянно.

Оба интерпретируют байтовые коды; зачем называть одну виртуальной машиной, а другую переводчиком?

twils
источник

Ответы:

137

Виртуальная машина - это виртуальная вычислительная среда с определенным набором атомарных четко определенных инструкций, которые поддерживаются независимо от какого-либо конкретного языка, и ее обычно рассматривают как «песочницу» для себя. ВМ аналогична набору команд конкретного ЦП и имеет тенденцию работать на более фундаментальном уровне с очень простыми строительными блоками таких инструкций (или байтовыми кодами), которые не зависят от следующего. Инструкция выполняется детерминистически на основе только текущего состояния виртуальной машины и не зависит от информации в другом месте в потоке команд в этот момент времени.

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

Компилятор Java преобразует язык Java в поток байтового кода, не отличающийся от компилятора C, который преобразует программы на языке C в ассемблерный код. Интерпретатор, с другой стороны, на самом деле не преобразует программу в какую-либо четко определенную промежуточную форму, он просто выполняет действия программы как часть процесса интерпретации источника.

Еще один тест на разницу между виртуальной машиной и интерпретатором заключается в том, считаете ли вы ее независимой от языка. То, что мы знаем как Java VM, на самом деле не специфично для Java. Вы можете создать компилятор из других языков, что приведет к байт-кодам, которые могут быть запущены в JVM. С другой стороны, я не думаю, что мы действительно подумали бы о «компиляции» другого языка, кроме Python, в Python для интерпретации интерпретатором Python.

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

Высокий Джефф
источник
7
У меня сложилось впечатление, что python сгенерировал байт-код, pyc или это то, на что вы ссылаетесь, «помогите ускорить такие интерпретируемые языки, вот где мы можем определить промежуточные формы предварительно проанализированного, предварительно токенизированного исходного кода, который более с готовностью прямо интерпретируется ".
Джеймс МакМахон
32
@InSciTek Джефф: Из вашего ответа не ясно, знаете ли вы, что Python тоже использует виртуальную машину.
tzot
3
@TZ - популярная реализация Python - это компилятор Python с обратной стороной виртуальной машины. В интерактивном режиме он немного гибридный как с интерфейсом интерпретатора, так и с компонентом компилятора. Однако это варианты реализации. Я пытался описать разницу между концепцией VM и интерпретатором
Tall Jeff
8
On the other hand, I don't think we would really think of "compiling" some other language other than Python into Python for interpretation by the Python interpreter.Можно написать язык, который может быть скомпилирован в байт-код Python, точно так же, как Scala скомпилирован в байт-код Java. В интерактивном режиме интерактивная оболочка Python компилирует вашу набранную команду в байт-код и выполняет этот байт-код. Вы можете написать свою собственную оболочку, используя eval и exec, и вы можете использовать встроенную функцию compile (), чтобы превратить строку в байт-код.
Ли Райан
4
@ Ли Райан: Да, но это официально не поддерживается, как в случае с JVM. В Python байт-код является недокументированной деталью реализации.
Сурьма
159

В этом посте «виртуальная машина» относится к виртуальным машинам процесса, а не к системным виртуальным машинам, таким как Qemu или Virtualbox. Виртуальная машина процесса - это просто программа, которая обеспечивает общую среду программирования - программу, которая может быть запрограммирована.

В Java есть как интерпретатор, так и виртуальная машина, а в Python есть виртуальная машина и интерпретатор. Причина, по которой «виртуальная машина» является более распространенным термином в Java, а «интерпретатор» - более распространенный термин в Python, во многом связана с основным отличием между двумя языками: статическая типизация (Java) и динамическая типизация (Python). В этом контексте «тип» относится к примитивным типам данных - типам, которые предполагают размер данных в памяти. Виртуальная машина Java имеет это легко. Это требует от программиста указать примитивный тип данных каждой переменной. Это обеспечивает достаточную информацию для байт-кода Java не только для интерпретации и выполнения виртуальной машиной Java, но даже для компиляции в машинные инструкции, Виртуальная машина Python является более сложной в том смысле, что она выполняет дополнительную задачу приостановки перед выполнением каждой операции, чтобы определить примитивные типы данных для каждой переменной или структуры данных, участвующих в операции. Python освобождает программиста от мышления в терминах примитивных типов данных и позволяет выражать операции на более высоком уровне. Цена этой свободы - производительность. «Интерпретатор» является предпочтительным термином для Python, потому что он должен делать паузу для проверки типов данных, а также потому, что сравнительно лаконичный синтаксис языков с динамической типизацией хорошо подходит для интерактивных интерфейсов. Технического барьера для создания интерактивного Java-интерфейса нет, но попытка написать статически типизированный код в интерактивном режиме была бы утомительной, так что просто так не делается.

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

переносимый интерпретируемый статически типизированный язык

Следующая ближайшая вещь - LLVM, но LLVM работает на другом уровне:

переносимый интерпретируемый язык ассемблера

Термин «байт-код» используется как в Java, так и в Python, но не все байт-коды созданы одинаковыми. Байт-код - это просто общий термин для промежуточных языков, используемых компиляторами / интерпретаторами. Даже компиляторы C, такие как gcc, используют промежуточный язык (или несколько) для выполнения работы. Байт-код Java содержит информацию о примитивных типах данных, а байт-код Python - нет. В этом отношении виртуальная машина Python (и Bash, Perl, Ruby и т. Д.) Действительно существенно медленнее, чем виртуальная машина Java, или, скорее, у нее просто больше работы. Полезно рассмотреть, какая информация содержится в разных форматах байт-кода:

  • регистры llvm: cpu
  • Java: примитивные типы данных
  • Python: пользовательские типы

Чтобы провести реальную аналогию: LLVM работает с атомами, виртуальная машина Java работает с молекулами, а виртуальная машина Python работает с материалами. Поскольку в конечном итоге все должно быть разложено на субатомные частицы (операции с реальной машиной), виртуальная машина Python выполняет самую сложную задачу.

Интерпретаторы / компиляторы статически типизированных языков просто не имеют того багажа, который имеют интерпретаторы / компиляторы динамически типизированных языков. Программисты статически-типизированных языков должны взять на себя слабость, за которую платят производительность. Однако, как все недетерминированные функции являются тайно детерминированными, так и все языки с динамической типизацией тайно статически типизированы. Поэтому различия в производительности между этими двумя языковыми семействами должны выравниваться во время, когда Python меняет свое имя на HAL 9000.

Виртуальные машины динамических языков, таких как Python, реализуют некоторую идеализированную логическую машину и не обязательно очень близко соответствуют какому-либо реальному физическому оборудованию. Виртуальная машина Java, напротив, больше похожа по функциональности на классический компилятор C, за исключением того, что вместо генерации машинных инструкций она выполняет встроенные подпрограммы. В Python целое число - это объект Python с кучей атрибутов и методов, прикрепленных к нему. В Java int - это назначенное количество битов, обычно 32. Это не совсем справедливое сравнение. Целые числа Python действительно должны сравниваться с классом Java Integer. Примитивный тип данных "int" в Java не может сравниться ни с чем в языке Python, потому что в языке Python просто отсутствует этот слой примитивов, как и байт-код Python.

Поскольку Java-переменные явным образом типизированы, можно ожидать, что что-то вроде производительности Jython будет находиться на том же уровне, что и cPython . С другой стороны, виртуальная машина Java, реализованная в Python, почти гарантированно будет медленнее, чем грязь. И не ждите, что Ruby, Perl и т. Д. Будут лучше. Они не были предназначены для этого. Они были разработаны для «сценариев», что называется программированием на динамическом языке.

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

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

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

Наконец, чтобы рассмотреть все в перспективе, рассмотрим следующее: программа на Python, выполняемая интерпретатором / виртуальной машиной Python, реализованная на Java, работающая на интерпретаторе / виртуальной машине Java, реализованная в LLVM, на виртуальной машине qemu, работающей на iPhone.

Постоянная ссылка

оборота поориорик
источник
1
trying to write any statically-typed code interactively would be tedious, Если вы знаете OCaml и Haskell, вы увидите, что это неправда, поскольку они являются очень лаконичными статически типизированными языками.
Матиас Браун
@MatthiasBraun Я могу согласиться с тем, что эти функциональные языки создают краткий код, но это не обязательно означает, что они хорошо подходят для интерактивного режима. Если бы OCaml и Haskell были напечатаны динамически, как lisp, они бы работали лучше для интерактивного режима, я полагаю.
бомбы
58

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

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

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

Мистер Фуз
источник
1
Я согласен. Эта разница в терминологии действительно сводится к опыту конечного пользователя (разработчика). Это не имеет ничего общего с реальными техническими различиями, так как техническая линия настолько невероятно размыта, что почти не существует.
Коди Брошиус
1
+1: и - что более важно - какой смысл? Какую программу вы не можете написать из-за этого различия? Какая трассировка стека вас смущает? Какая библиотека не работает правильно?
S.Lott
@ S.Lott Потому что всегда приятно побеждать с коллегами. ;)
Qix - МОНИКА БЫЛА ОСТАЛАСЬ
16

Интерпретатор , переводит исходный код в некоторое эффективное промежуточное представление (код) и немедленно выполняет это.

Виртуальная машина явно выполняет хранимый предварительно скомпилированный код, созданный компилятором, который является частью системы интерпретатора.

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

В случае с python, если мы храним pyc- файлы, как упомянуто в комментарии к этому посту, механизм станет больше похож на виртуальную машину , и этот байт-код будет выполняться быстрее - он все равно будет интерпретироваться, но с гораздо более дружественной к компьютеру форме , Если мы посмотрим на это в целом, PVM - это последний шаг Python Interpreter.

Суть в том, что когда мы ссылаемся на Python Interpreter, это означает, что мы ссылаемся на него в целом, а когда мы говорим PVM, это означает, что мы просто говорим о части Python Interpreter, среде выполнения. Как и в Java, мы ссылаемся на разные части, такие как: JRE, JVM, JDK и т. Д.

Более того, статья в Википедии: переводчик и виртуальная машина . Еще один здесь . Здесь вы можете найти Сравнение приложений виртуальных машин . Это помогает понять разницу между компиляторами, интерпретаторами и виртуальными машинами.

Адель Ансари
источник
12

Термин интерпретатор является устаревшим термином, восходящим к более ранним языкам сценариев оболочки. Поскольку «языки сценариев» превратились в полнофункциональные языки, а их соответствующие платформы стали более изощренными и изолированными, различие между виртуальной машиной и интерпретатором (в смысле Python) очень мало или вообще отсутствует.

Интерпретатор Python по-прежнему функционирует так же, как сценарий оболочки, в том смысле, что он может быть выполнен без отдельного шага компиляции. Кроме того, различия между интерпретатором Python (или Perl или Ruby) и виртуальной машиной Java - это в основном детали реализации. (Можно утверждать, что Java более полно изолирована, чем Python, но в конечном итоге оба предоставляют доступ к базовой архитектуре через собственный интерфейс C).

Даниэль Нааб
источник
1
Существуют Java-оболочки, которые могут запускать Java-код без отдельных (видимых пользователю) шагов компиляции.
Ли Райан
1
дай мне имя: D
Мацей Новицкий
11

Чтобы дать глубокий ответ на вопрос « Почему виртуальная машина Java, а не интерпретатор Python? », Давайте попытаемся вернуться к области теории компиляции в качестве отправной точки обсуждения.

Типичный процесс компиляции программы включает в себя следующие этапы:

  1. Лексический анализ . Разбивает текст программы на осмысленные «слова», называемые токенами (как часть процесса удаляются все комментарии, пробелы, новые строки и т. Д., Поскольку они не влияют на поведение программы). Результатом является упорядоченный поток токенов.
  2. Синтаксический анализ . Создает так называемое абстрактное синтаксическое дерево (AST) из потока токенов. AST устанавливает отношения между токенами и, как следствие, определяет порядок оценки программы.
  3. Семантический анализ . Проверяет семантическую правильность AST, используя информацию о типах и набор семантических правил языка программирования. (Например, a = b + cэто правильное утверждение с точки зрения синтаксиса, но совершенно неверное с семантической точки зрения, если оно aбыло объявлено как постоянный объект)
  4. Промежуточная генерация кода . Сериализует AST в линейно упорядоченный поток машинно-независимых «примитивных» операций. Фактически, генератор кода обходит AST и регистрирует порядок шагов оценки. В результате из древовидного представления программы мы получаем гораздо более простое представление в виде списка, в котором сохраняется порядок оценки программы.
  5. Генерация машинного кода . Программа в виде машинно-независимого «примитивного» байт-кода преобразуется в машинный код конкретной архитектуры процессора.

Хорошо. Теперь давайте определимся с терминами.

Интерпретатор в классическом смысле этого слова предполагает выполнение на основе оценки программы, основанной на AST, полученной непосредственно из текста программы . В этом случае программа распространяется в виде исходного кода, а интерпретатор заполняется текстом программы, часто динамическим способом (оператор за оператором или строка за строкой). Для каждого оператора ввода интерпретатор создает свой AST и сразу же оценивает его, изменяя «состояние» программы. Это типичное поведение, демонстрируемое скриптовыми языками. Рассмотрим, например, Bash, Windows CMD и т. Д. Концептуально, Python тоже так поступает.

Если мы заменим шаг выполнения на основе AST на генерацию промежуточного машинно-независимого шага двоичного байт-кода в интерпретаторе, мы разделим весь процесс выполнения программы на две отдельные фазы: компиляция и выполнение. В этом случае то, что раньше было интерпретатором, станет компилятором байт-кода, который преобразует программу из формы текста в некоторую двоичную форму. Затем программа распространяется в этой двоичной форме, но не в форме исходного кода. На пользовательской машине этот байт-код подается в новую сущность - виртуальную машину , которая фактически интерпретирует этот байт-код. За счет этого виртуальные машины также называют интерпретатором байт-кода . Но обратите внимание здесь! Классический переводчиктекстовый интерпретатор , но виртуальная машина - это двоичный интерпретатор ! Это подход, принятый Java и C #.

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

Теперь вернемся к исходному вопросу и рассмотрим Java против Python.

Изначально Java был спроектирован так, чтобы иметь как можно меньше зависимостей реализации. Его дизайн основан на принципе «пиши один раз, беги куда угодно» (WORA). Для его реализации Java изначально была разработана как язык программирования, который компилируется в машинно-независимый двоичный байт-код , который затем может выполняться на всех платформах, поддерживающих Java, без необходимости его перекомпиляции. Вы можете думать о Java как о C ++ на основе WORA . На самом деле Java ближе к C ++, чем к языкам сценариев, таким как Python . Но в отличие от C ++ , Javaбыл спроектирован для компиляции в двоичный байт-код, который затем выполняется в среде виртуальной машины , в то время как C ++ был спроектирован для компиляции в машинном коде и последующего непосредственного выполнения целевым процессором.

Первоначально Python был разработан как своего рода язык программирования сценариев, который интерпретирует сценарии (программы в форме текста, написанного в соответствии с правилами языка программирования). Из-за этого Python изначально поддерживал динамическую интерпретацию однострочных команд или операторов, как это делают Bash или Windows CMD. По той же причине, первоначальные реализации Python не имели каких-либо компиляторов байт-кода и виртуальных машин для выполнения такого байт-кода внутри, но с самого начала Python требовал интерпретатора, который способен понимать и оценивать текст программы Python .

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

В настоящее время Python также имеет виртуальную машину под капотом и может компилировать и интерпретировать байт-код Python. И этот факт делает дополнительные инвестиции в путаницу: « Почему виртуальная машина Java, а интерпретатор Python?и что программы будут демонстрировать точно такое же поведение и будут производить одинаково одинаковые выходные данные с одинакового входа. Единственным заметным отличием будет скорость выполнения программы и объем памяти, потребляемый интерпретатором. Таким образом, виртуальная машина в Python - это не неизбежная часть языкового дизайна, а просто необязательное расширение основного интерпретатора Python.

Java можно рассматривать аналогичным образом. Java под капотом имеет JIT-компилятор и может выборочно компилировать методы класса Java в машинный код целевой платформы и затем непосредственно выполнять его. Но! Java все еще использует интерпретацию байт-кода в качестве основного способа выполнения Java-программы. Подобно реализациям Python, в которых виртуальные машины используются исключительно как метод оптимизации, виртуальные машины Java используют компиляторы Just-In-Time исключительно для целей оптимизации. Точно так же, просто из-за того, что прямое выполнение машинного кода как минимум в десять раз быстрее, чем интерпретация байт-кода Java. Как и в случае с Python, наличие JIT-компилятора под капотом JVM абсолютно прозрачно как для разработчиков языка Java, так и для разработчиков программ на Java. Тот же язык программирования Java может быть реализован JVM с JIT-компилятором и без него. Точно так же одни и те же программы могут выполняться в JVM с JIT внутри и без него, и одни и те же программы будут демонстрировать одинаковое поведение и одинаково выводить одинаковые выходные данные на обоих входах JVM (с JIT и без него). Как и в случае с Python, единственное заметное различие между ними заключается в скорости выполнения и объеме памяти, используемой JVM. И, наконец, как и в случае с Python, JIT в Java также не является неизбежной частью дизайна языка, но является необязательным расширением основных реализаций JVM. и одни и те же программы будут демонстрировать абсолютно одинаковое поведение и одинаково создавать одинаковые выходные данные с одинакового входа на обеих виртуальных машинах (с JIT и без него). Как и в случае с Python, единственное заметное различие между ними заключается в скорости выполнения и объеме памяти, используемой JVM. И, наконец, как и в случае с Python, JIT в Java также не является неизбежной частью дизайна языка, но является необязательным расширением основных реализаций JVM. и одни и те же программы будут демонстрировать абсолютно одинаковое поведение и одинаково создавать одинаковые выходные данные с одинакового входа на обеих виртуальных машинах (с JIT и без него). Как и в случае с Python, единственное заметное различие между ними заключается в скорости выполнения и объеме памяти, используемой JVM. И, наконец, как и в случае с Python, JIT в Java также не является неизбежной частью дизайна языка, но является необязательным расширением основных реализаций JVM.

С точки зрения проектирования и реализации виртуальных машин Java и Python они существенно различаются, хотя (внимание!) Обе остаются виртуальными машинами. JVM является примером низкоуровневой виртуальной машины с простыми базовыми операциями и высокой стоимостью отправки команд. Python, в свою очередь, представляет собой высокоуровневую виртуальную машину, для которой инструкции демонстрируют сложное поведение, а стоимость отправки инструкций не столь значительна. Java работает с очень низким уровнем абстракции. JVM работает с небольшим четко определенным набором примитивных типов и имеет очень тесное соответствие (обычно один к одному) между инструкциями байт-кода и инструкциями собственного машинного кода. Напротив, виртуальная машина Python работает на высоком уровне абстракции, она работает со сложными типами данных (объектами) и поддерживает специальный полиморфизм, в то время как инструкции байт-кода демонстрируют сложное поведение, которое может быть представлено последовательностью нескольких инструкций машинного кода. Например, Python поддерживает математику неограниченного диапазона. Таким образом, Python VM вынуждена использовать длинную арифметику для потенциально больших целых чисел, для которых результат операции может переполнить машинное слово. Следовательно, одна инструкция байт-кода для арифметики в Python может быть представлена ​​в вызове функции внутри Python VM, тогда как в JVM арифметическая операция будет представлена ​​в виде простой операции, выраженной одной или несколькими собственными машинными инструкциями. Таким образом, Python VM вынуждена использовать длинную арифметику для потенциально больших целых чисел, для которых результат операции может переполнить машинное слово. Следовательно, одна инструкция байт-кода для арифметики в Python может быть представлена ​​в вызове функции внутри Python VM, тогда как в JVM арифметическая операция будет представлена ​​в виде простой операции, выраженной одной или несколькими собственными машинными инструкциями. Таким образом, Python VM вынуждена использовать длинную арифметику для потенциально больших целых чисел, для которых результат операции может переполнить машинное слово. Следовательно, одна инструкция байт-кода для арифметики в Python может быть представлена ​​в вызове функции внутри Python VM, тогда как в JVM арифметическая операция будет представлена ​​в виде простой операции, выраженной одной или несколькими собственными машинными инструкциями.

В результате мы можем сделать следующие выводы. Виртуальная машина Java, но интерпретатор Python, потому что:

  1. Термин «виртуальная машина» предполагает интерпретацию двоичного байт-кода, тогда как термин «интерпретатор» предполагает интерпретацию текста программы.
  2. Исторически Java была разработана и реализована для двоичной интерпретации байт-кода, а Python изначально был разработан и реализован для интерпретации текста программы. Таким образом, термин «виртуальная машина Java» является историческим и хорошо зарекомендовал себя в сообществе Java. Точно так же термин «интерпретатор Python» является историческим и хорошо зарекомендовал себя в сообществе Python. Народы стремятся продлить традицию и использовать те же термины, которые использовались задолго до этого.
  3. Наконец, в настоящее время для Java интерпретация двоичного байт-кода является основным способом выполнения программ, в то время как JIT-компиляция является просто необязательной и прозрачной оптимизацией. А для Python в настоящее время интерпретация текста программы является основным способом выполнения программ Python, в то время как компиляция в байт-код Python VM является просто необязательной и прозрачной оптимизацией.

Поэтому и Java, и Python имеют виртуальные машины, которые являются двоичными интерпретаторами байт-кода, что может привести к путанице, такой как « Почему виртуальная машина Java, а не интерпретатор Python?". Ключевым моментом здесь является то, что для Python виртуальная машина не является основным или необходимым средством выполнения программы; это всего лишь необязательное расширение классического интерпретатора текста. С другой стороны, виртуальная машина является ядром и неизбежна часть экосистемы выполнения Java-программ. Выбор статической или динамической типизации для дизайна языка программирования в основном влияет только на уровень абстракции виртуальной машины, но не определяет, нужна ли виртуальная машина. Языки, использующие обе системы типизации, могут быть скомпилированы интерпретируется или выполняется в среде виртуальной машины в зависимости от желаемой модели выполнения.

Заратустра
источник
2
Это должен быть выбран в качестве официального ответа ИМХО.
Равикант Андхаварапу
Официальный ответ должен быть ДА, поскольку «и Java, и Python имеют виртуальные машины, являются двоичными интерпретаторами байт-кода». Период.
Stuartw
10

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

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

Не забывайте, что в Python есть компиляторы JIT для x86, что еще больше запутывает проблему. (См. Психо).

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

Arafangion
источник
1
Это неверно. Во-первых, не существует такого понятия, как «интерпретируемый язык». Независимо от того, использует ли реализация компилятор или интерпретатор, это не черта языка, а реализация. Во-вторых, из 13 или около того реализаций Ruby точно 1 является интерпретатором, все остальные имеют компиляторы.
Йорг Миттаг
2
В-третьих, Ruby не медлителен. Ни один язык не является медленным, потому что скорость - это не черта языка, а языковая реализация. Из 13 или около того реализаций Ruby некоторые медленнее, чем некоторые из 7 реализаций Python, некоторые быстрее.
Йорг Миттаг
Я думаю, что он сравнивает стандартные реализации здесь Йорг. CPython и Ruby (я думаю, что официальная реализация называется просто Ruby).
Джеймс МакМахон
Хотя Арафангион может ссылаться на «стандартные» реализации, он должен был сказать так. Я Pythonista, но я ненавижу любое утверждение вида "Язык X медленный", так как я согласен с Йоргом в вопросе реализаций.
tzot
1
Именно поэтому я сказал «был (есть?)», И особенно термин «медленнее». Нигде я не говорил, что Ruby сам по себе медленный.
Арафангион
2

Python может интерпретировать код, не компилируя его в байт-код. Ява не может .

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

(из документации).

В Java каждый файл должен быть скомпилирован в .classфайл, который затем запускается на JVM. Напротив, python делает то, что импортируется вашим основным скриптом, чтобы ускорить последующее использование этих файлов.

Однако в типичном случае большая часть кода Python (по крайней мере, CPython) выполняется на эмулируемой машине стека, в которой инструкции почти идентичны инструкциям JVM, поэтому нет большой разницы.

Однако настоящая причина такого расхождения заключается в том, что с самого начала java маркировалась как «переносимый исполняемый байт-код», а python - как динамический интерпретируемый язык с REPL. Имена придерживаются!

blue_note
источник
0

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

Теперь к вашему вопросу:

что такое переводчик (в информатике)

Он переводит исходный код на наименьший исполняемый модуль, а затем выполняет этот модуль.

что такое виртуальная машина

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

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

зачем использовать слово «переводчик» при разговоре о питоне

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

mightyWOZ
источник
0

Нет, они оба не интерпретируют байт-код.

Python интерпретирует байт-код, только если вы работаете с pypy. В противном случае он компилируется в C и интерпретируется на этом уровне.

Java компилируется в байт-код.

Майкл Тамиллоу
источник
Можете ли вы дать какие-либо ресурсы для вашего ответа?
Исуру Дилшан,
и это на Java: en.wikipedia.org/wiki/Java_virtual_machine
Майкл Тамиллоу,
Вот что не так с переполнением стека. У кого-то вспыльчивость, потому что он вызван и выражает это отрицательными голосами.
Майкл Тамиллоу
0

Я думаю, что границы между обоими размыты, люди в основном спорят о значении слова «интерпретатор» и о том, насколько близко язык стоит к каждой стороне спектра «интерпретатор ... компилятор». Ни один не делает 100% как бы то ни было. Я думаю, что легко написать реализацию Java или Python, которая имеет любое значение спектра.

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

Аргумент о том, что Python не имеет официально определенного байт-кода и существует только в памяти, также не убеждает меня, просто потому, что я планирую разработать устройства, которые будут распознавать только байт-код Python, а часть компиляции будет выполнена на компьютере JS браузера.

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

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

Олег Гордеев
источник
0

для сообщений, которые упоминают, что python не должен генерировать байт-код, я не уверен, что это правда. кажется, что все вызываемые в Python должны иметь .__code__.co_codeатрибут, который содержит байт-код. Я не вижу смысла называть python «не скомпилированным» только потому, что скомпилированные артефакты не могут быть сохранены; и часто не сохраняются при проектировании в Python, например, все средства компиляции компилируют новый байт-код для своего ввода, это является причиной того, что область действия переменной понимания не согласована между compile(mode='exec, ...)и компилируется, compile(mode='single', ...)например, между запуском сценария Python и использованием pdb

ThorSummoner
источник