Java "Віртуальна машина" проти мови Python "Інтерпретатор"?


207

Здається, рідко читати Python "віртуальної машини", а на Java "віртуальна машина" використовується весь час.

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

Відповіді:


137

Віртуальна машина - це віртуальне обчислювальне середовище з певним набором чітко визначених атомних інструкцій, які підтримуються незалежно від будь-якої конкретної мови, і це, як правило, вважається пісочницею для себе. VM є аналогом набору інструкцій певного процесора і прагне працювати на більш фундаментальному рівні з дуже базовими складовими таких інструкцій (або байтових кодів), які не залежать від наступних. Інструкція виконується детерміновано лише на основі поточного стану віртуальної машини і не залежить від інформації в іншому місці потоку інструкцій у той момент часу.

Інтерпретатор, з іншого боку, більш досконалий тим, що він призначений для розбору потоку синтаксису певної мови та певного граммеру, який повинен бути розшифрований у контексті оточуючих лексем. Ви не можете дивитися на кожен байт або навіть кожен рядок окремо і точно знати, що робити далі. Лексеми на мові не можна сприймати окремо, як це стосується інструкцій (байтових кодів) VM.

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

Ще один тест на відмінність між ВМ та перекладачем - чи вважаєте ви це незалежним від мови. Те, що ми знаємо як Java VM, насправді не є специфічним для Java. Ви можете зробити компілятор з інших мов, що призводить до байтових кодів, які можна запустити на JVM. З іншого боку, я не думаю, що ми б дійсно думали про "компіляцію" іншої мови, крім Python, в Python для інтерпретації інтерпретатором Python.

Через складність процесу інтерпретації це може бути відносно повільним процесом .... конкретно розбираючи та ідентифікуючи мовні лексеми тощо, та розуміючи контекст джерела, щоб мати можливість здійснити процес виконання в інтерпретаторі. Щоб допомогти прискорити такі інтерпретовані мови, саме тут ми можемо визначити проміжні форми попередньо проаналізованого попередньо токенізованого вихідного коду, який легше інтерпретується безпосередньо. Цей вид бінарної форми все ще інтерпретується під час виконання, він лише починається від значно менш читаної людини форми для підвищення продуктивності. Однак логіка, що виконує цю форму, не є віртуальною машиною, тому що ці коди все ще не можуть бути взяті окремо - контекст навколишніх жетонів все ще має значення, вони лише зараз знаходяться в іншій більш ефективному для комп'ютера формі.


7
У мене склалося враження, що python генерує байт-код, pyc, або це те, на що ви посилаєтесь, "допоможіть прискорити такі інтерпретовані мови, саме тут ми можемо визначити проміжні форми попередньо проаналізованого попередньо токенізованого вихідного коду. легко інтерпретується ".
Джеймс Макмахон

32
@InSciTek Jeff: З вашої відповіді не зрозуміло, чи знаєте ви, що 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
@Lie Ryan так, але це офіційно не підтримується, як це є у 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: регістри процесора
  • Java: примітивні типи даних
  • Python: типи, визначені користувачем

Для здійснення аналогії в реальному світі: LLVM працює з атомами, віртуальна машина Java працює з молекулами, а віртуальна машина Python працює з матеріалами. Оскільки в кінцевому підсумку все повинно розкладатися на субатомні частинки (реальні операції з машиною), віртуальна машина Python має найскладніше завдання.

Інтерпретатори / компілятори мов статичного типу просто не мають того самого багажу, який мають перекладачі / укладачі динамічно набраних мов. Програмістам мов, які мають статичний тип, доводиться брати на себе слабкість, за яку виграш - це продуктивність. Однак, як і всі недетерміновані функції таємно детерміновані, так і всі динамічно набрані мови таємно статично введені. Тому різниці в роботі між двома мовними сім'ями повинні вирівнюватися приблизно в той час, коли Python змінює свою назву на HAL 9000.

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

Оскільки змінні Java явно набрані, можна з розумом очікувати, що щось на зразок продуктивності Jython буде таким самим тестом, що і cPython . З іншого боку, віртуальна машина Java, реалізована в Python, майже гарантована повільніше, ніж грязь. І не сподівайтеся, що Рубі, Перл і т.д., не зможуть вийти краще. Вони не були створені для цього. Вони були розроблені для "сценаріїв", саме так називається програмування в динамічній мові.

Кожна операція, яка відбувається у віртуальній машині, зрештою повинна вражати справжнє обладнання. Віртуальні машини містять попередньо складені процедури, які є загальними для виконання будь-якої комбінації логічних операцій. Віртуальна машина може не випромінювати нові інструкції на машині, але, безумовно, вона виконує свої власні процедури знову і знову в арбітрально складних послідовностях. Віртуальна машина 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
Я згоден. Ця різниця в термінології дійсно зводиться до досвіду кінцевого споживача (розробника, тобто). Це не має нічого спільного з реальними технічними розбіжностями, оскільки технічна лінія настільки неймовірно розмита, що її чорт майже не існує.
Cody Brocious

1
+1: І - що важливіше - в чому сенс? Яку програму ви не можете написати через цю відмінність? Що прослідкування стека вас бентежить? Яка бібліотека не працює належним чином?
S.Lott

@ S.Lott Тому що завжди добре перемагати аргументи з колегами. ;)
Qix - МОНІКА ПОМИЛИЛА

16

Інтерпретатор переводить вихідний код в якесь ефективне проміжне подання (код) і негайно виконує це.

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

Дуже важливою характеристикою віртуальної машини є те, що програмне забезпечення, що працює всередині, обмежується ресурсами, які надає віртуальна машина. Саме він не може вирватися зі свого віртуального світу. Подумайте про безпечне виконання віддаленого коду, Java Applets.

У випадку з python, якщо ми тримаємо pyc файли , як це було зазначено в коментарі до цього повідомлення, тоді механізм став би більше схожий на VM, і цей байт-код виконується швидше - він все одно буде інтерпретований, але з набагато більш дружньої форми для комп'ютера . Якщо ми розглянемо це в цілому, PVM - це останній крок інтерпретатора Python.

Підсумкова лінія є, коли ми посилаємося на інтерпретатора Python, це означає, що ми маємо на увазі його в цілому, а коли ми кажемо PVM, це означає, що ми просто говоримо про частину інтерпретатора Python, середовище виконання. Подібно до Java, ми позначаємо різні частини дивелліл, JRE, JVM, JDK тощо.

Докладніше про записи Вікіпедії: перекладач та віртуальна машина . Ще одна тут . Тут ви можете порівняти віртуальні машини додатків . Це допомагає зрозуміти різницю між компіляторами, перекладачами та VM.


12

Термін "перекладач" - це успадкований термін, який починається з попередніх мов сценарію оболонок. Оскільки "мови сценаріїв" перетворилися на повнофункціональні мови та відповідні їм платформи стали більш досконалими та пісочницями, відмінність між віртуальною машиною та інтерпретатором (у сенсі Python) дуже мала чи не існує.

Інтерпретатор Python як і раніше функціонує так само, як і сценарій оболонки, в тому сенсі, що він може бути виконаний без окремого кроку компіляції. Крім того, відмінності між інтерпретатором Python (або Perl або Ruby) та віртуальною машиною Java - це переважно деталі реалізації. (Можна стверджувати, що Java є більш повною мірою, ніж Python, але обидва в кінцевому підсумку забезпечують доступ до базової архітектури через власний інтерфейс С.)


1
Є оболонки Java, які можуть запускати код Java без окремих етапів компіляції (видимі користувачеві).
Lie Lie Ryan

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 vs 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 під кришкою має компілятор 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. і ті ж програми демонструватимуть однакову поведінку та даватимуть однаково один і той самий вихід із рівних входів на обох JVM (з JIT і без). І, як і у випадку з Python, єдиною помітною різницею між ними буде швидкість виконання та кількість пам'яті, споживаної JVM. І нарешті, як і у випадку з Python, JIT на Java також не є неминучою частиною мовного дизайну, а лише необов'язковим розширенням основних реалізацій JVM. і ті ж програми демонструватимуть однакову поведінку та даватимуть однаково один і той самий вихід із рівних входів на обох 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
Я кину тобі тут кістку, бо думаю, що це, мабуть, справжня відповідь, і ти проголосував за відсутність шматочків.
vikingben

3

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

Більш сувора інтерпретація «інтерпретованої мови» стає корисною лише тоді, коли обговорюються питання про продуктивність VM, наприклад, порівняно з Python, Рубі вважався (є?) Повільнішим, оскільки це інтерпретована мова, на відміну від Python - в інших слова, контекст - це все.


1
Це неправильно. По-перше, не існує такого поняття, як "інтерпретована мова". Незалежно від того, чи використовується у використанні компілятор чи інтерпретатор, це не властивість мови, а реалізація. По-друге, з 13 або більше реалізацій Ruby, рівно 1 є інтерпретатором, всі інші мають компілятори.
Йорг W Міттаг

2
По-третє, Рубі не повільний. Жодна мова не повільна, тому що швидкість - це не риса мови, а мовна реалізація. З 13 або більше реалізацій Ruby деякі з них повільніші, ніж деякі з 7-ма реалізацій Python, деякі - швидшими.
Йорг W Міттаг

Я думаю, що він порівнює тут стандартні реалізації Jörg. CPython та Ruby (я думаю, офіційна реалізація саме названа Ruby).
Джеймс Макмахон

Хоча Arafangion, можливо, посилається на "стандартні" реалізації, він повинен був так сказати. Я Pythonista, але ненавиджу будь-яке твердження форми "Мова X повільна", оскільки я погоджуюся з Йоргом щодо питання реалізації.
tzot

1
Саме тому я сказав "був (є?)", І особливо термін "повільніше". Ніде я не сказав, що Рубі сама по собі повільна.
Арафангіон

2

Python може інтерпретувати код, не компілюючи його в байт-код. Java не може .

Python - це інтерпретована мова, на відміну від складеної, хоча відмінність може бути розмитою через наявність компілятора байт-коду. Це означає, що вихідні файли можна запускати безпосередньо без явного створення виконуваного файлу, який потім запускається.

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

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

Однак у типовому випадку більшість коду python (щонайменше, CPython) працює у емульованій машині стека, яка має майже ідентичні вказівки до інструкцій JVM, тому великої різниці немає.

Однак справжньою причиною дистрибуції є те, що з самого початку java назвала себе як "портативний, виконуваний байт-код", а python назвав себе динамічною, інтерпретованою мовою із REPL. Імена дотримуються!


0

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

Тепер до вашого питання:

що таке перекладач (з інформатики)

Він переводить вихідний код на найменший виконуваний блок, а потім виконує цей блок.

що таке віртуальна машина

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

як ви бачите, що інтерпретатор є частиною або JVM, і весь JVM не можна назвати перекладачем, оскільки він містить багато інших компонентів.

навіщо використовувати слово "Інтерпретатор", коли говорити про пітон

з java частина компіляції явна. З іншого боку, python не є явним, оскільки java щодо його компіляції та інтерпретації, з точки зору точки зору інтерпретації - єдиний механізм, який використовується для виконання програм python


0

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

Python інтерпретує байт-код лише у тому випадку, якщо ви працюєте з pypy. В іншому випадку вона компілюється в C та інтерпретується на цьому рівні.

Java компілюється в байт-код.


Чи можете ви дати якісь ресурси для своєї відповіді?
Ісуру Ділшан


Це те, що не так із Stack Overflow. У когось приємно підходить, тому що вони викликаються і виражають це попутними голосами.
Майкл Таміллоу

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.