Java "Виртуальная машина" и Python "Переводчик" на языке? - PullRequest
184 голосов
/ 14 января 2009

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

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

Ответы [ 10 ]

146 голосов
/ 14 ноября 2009

В этом посте «виртуальная машина» относится к виртуальным машинам процесса, а не к системные виртуальные машины, такие как 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: регистры процессора
  • Java: примитивные типы данных
  • Python: пользовательские типы

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

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

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

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

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

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

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

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

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

123 голосов
/ 14 января 2009

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

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

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

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

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

57 голосов
/ 14 января 2009

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

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

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

14 голосов
/ 14 января 2009

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

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

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

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

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

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

12 голосов
/ 14 января 2009

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

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

9 голосов
/ 14 января 2009

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

5 голосов
/ 18 ноября 2018

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

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

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

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

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

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

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

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

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

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

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

В настоящее время Python также имеет виртуальную машину под капотом и может компилировать и интерпретировать байт-код Python. И этот факт делает дополнительные инвестиции в путаницу " Почему виртуальная машина Java, а интерпретатор Python? ", потому что кажется, что реализации обоих языков содержат виртуальные машины. Но! Даже в настоящий момент интерпретация текста программы является основным способом выполнения программ на Python. Реализации Python используют виртуальные машины под капотом исключительно как метод оптимизации. Интерпретация двоичного байт-кода в виртуальной машине намного эффективнее, чем прямая интерпретация исходного текста программы. В то же время присутствие виртуальной машины в Python абсолютно прозрачно как для разработчиков языка Python, так и для разработчиков программ 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.

С точки зрения проектирования и реализации виртуальных машин Java и Python они существенно различаются, хотя (внимание!) Обе остаются виртуальными машинами. JVM является примером низкоуровневой виртуальной машины с простыми базовыми операциями и высокой стоимостью отправки команд. Python, в свою очередь, является высокоуровневой виртуальной машиной, для которой инструкции демонстрируют сложное поведение, а стоимость отправки инструкций не столь значительна. Java работает с очень низким уровнем абстракции. JVM работает с небольшим четко определенным набором примитивных типов и имеет очень тесное соответствие (обычно один к одному) между инструкциями байт-кода и инструкциями собственного машинного кода. Напротив, виртуальная машина Python работает на высоком уровне абстракции, она работает со сложными типами данных (объектами) и поддерживает специальный полиморфизм, в то время как инструкции байт-кода демонстрируют сложное поведение, которое может быть представлено последовательностью нескольких инструкций машинного кода. Например, Python поддерживает математику неограниченного диапазона. Таким образом, 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 Virtual Machine, но интерпретатор Python? ». Ключевым моментом здесь является то, что для Python виртуальная машина не является основным или необходимым средством выполнения программы; это просто необязательное расширение классического текстового интерпретатора. С другой стороны, виртуальная машина является ядром и неизбежной частью экосистемы выполнения Java-программ. Выбор статической или динамической типизации для дизайна языка программирования в основном влияет только на уровень абстракции виртуальной машины, но не определяет, нужна ли виртуальная машина. Языки, использующие обе системы ввода, могут быть скомпилированы, интерпретированы или выполнены в среде виртуальной машины в зависимости от желаемой модели выполнения.

3 голосов
/ 14 января 2009

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

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

0 голосов
/ 12 марта 2018

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

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

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

0 голосов
/ 01 октября 2016

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

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...