В чем преимущество системы трансляции выполнения программы, используемой в java

Обновлено: 21.11.2024

Современные языки программирования пытаются дать программистам возможность выполнять сложные действия на компьютере, при этом создавая инструкции для компьютера на языке, близком к их естественному языку. Например, большинству программистов достаточно удобно пользоваться стандартным математическим языком, чтобы использовать такие выражения, как 1/3*l*w*h (объем пирамиды с длиной основания l, шириной основания w и высотой час). Их не интересует последовательность машинных инструкций, необходимая для вычисления этого выражения, а тем более машинный код для этих инструкций.

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

Перевод программы

Обзор

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

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

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

Компиляторы

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

Переводчики

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

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

Виртуальные машины

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

Виртуальные машины

Перевод программы

При использовании виртуальной машины перевод программы выполняется в два этапа. Сначала программа компилируется на язык виртуальной машины. Когда программа выполняется, язык виртуальной машины интерпретируется в язык реальной машины. Это дает вам переносимость интерпретатора со значительно сниженными затратами на выполнение. С помощью интерпретатора виртуальной машины замедление выполнения можно уменьшить в 5–25 раз, в зависимости от характера программы.

Переносимость

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

История

Исторически идея виртуальной машины существует уже более 30 лет. В 1970-х годах язык программирования Pascal использовал виртуальные машины на некоторых платформах, чтобы упростить перенос программ Pascal с одной машины на другую.Один язык виртуальных машин, называемый P-code, использовался для поддержки разработки программ Pascal на ранних микропроцессорах. В дополнение к преимуществу переносимости, P-код был исключительно компактным, что было важным соображением, учитывая небольшой объем памяти в то время.

Точная компиляция

Соображения переносимости — мощная мотивация для использования интерпретаторов. Однако даже при использовании виртуальной машины накладные расходы на интерпретацию могут оказаться слишком большими для некоторых программ. Это привело к большому количеству исследований о том, как уменьшить накладные расходы. За последние несколько лет одна идея переместилась из области исследований в область практики: компиляция точно в срок (JIT).

Точно вовремя

Работа JIT-компилятора

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

Эффективность JIT-компиляции

Вы можете получить хорошее представление о том, почему JIT-компиляция так эффективна, принимая во внимание скорость современных процессоров и размер выполняемых ими программ. Современные процессоры способны выполнять около десяти миллиардов инструкций в секунду. Большая программа может содержать 10 миллионов инструкций. Это означает, что для выполнения в течение одной секунды каждая инструкция должна выполняться в среднем 1000 раз. Как правило, программы, разработка которых занимает разумное время, могут иметь серьезные проблемы во время выполнения только в том случае, если они выполняют некоторые части своего кода большое количество раз.

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

Смешивание языков

Накладные расходы на перевод виртуальной машины также можно уменьшить, определив стандартизированный способ включения кода, компилируемого в машинный язык базовой машины. Например, для языка Java существует стандарт Java Native Interface (JNI), который определяет, как код, скомпилированный из других языков, может быть включен в программу Java.

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

Принципы языков программирования

Цель лекции

  • Чтобы понять различные методологии реализации языков программирования.
  • Чтобы понять концепцию среды программирования
  • Концепции языков программирования Роберта В. Себесты.
  • «Принципы языков программирования», Сима Кедар.

Реализация языка программирования

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

Реализация языка программирования

  • Машинный язык компьютера — это набор инструкций.
  • В отсутствие другого вспомогательного программного обеспечения его собственный машинный язык является единственным языком, понятным большинству аппаратных компьютеров.
  • Теоретически компьютер можно спроектировать и построить, используя в качестве машинного языка определенный язык высокого уровня, но это будет очень сложно и дорого.
  • Кроме того, он будет крайне негибким, поскольку его будет сложно использовать с другими языками высокого уровня.
  • Более практичный вариант конструкции машины реализует аппаратно язык очень низкого уровня, который обеспечивает наиболее часто используемые примитивные операции и требует, чтобы системное программное обеспечение создавало интерфейс для программ на языках более высокого уровня.

Реализация языка программирования

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

Реализации языка программирования

  • Операционная система и языковые реализации накладываются на машинный язык интерфейса компьютера.
  • Эти уровни можно рассматривать как виртуальные компьютеры, предоставляющие пользователю интерфейсы на более высоких уровнях.
  • Например: операционная система и компилятор C предоставляют виртуальный компьютер C.

Многоуровневый интерфейс виртуального компьютера

Реализация языка программирования

  • Системы реализации первых языков программирования высокого уровня, созданные в конце 1950-х годов, были одними из самых сложных программных систем того времени.
  • В 1960-х годах были предприняты интенсивные исследования, чтобы понять и формализовать процесс создания этих высокоуровневых языковых реализаций.
  • Наибольшего успеха эти усилия достигли в области синтаксического анализа, прежде всего потому, что эта часть процесса реализации представляет собой применение частей теории автоматов и теории формального языка, которые тогда были хорошо изучены.
  • Языки программирования могут быть реализованы любым из трех основных способов.
    • Во-первых, Программа может быть переведена на машинный язык, который может выполняться непосредственно на компьютере. Этот метод называется реализацией компилятора.
    • Во-вторых, программы интерпретируются другой программой, называемой интерпретатором, без перевода. Этот метод называется чистой интерпретацией.
    • Системы реализации на третьем языке представляют собой компромисс между компиляторами и чистыми интерпретаторами, который называется гибридной системой реализации.
    • Программы могут быть переведены на машинный язык, который может выполняться непосредственно на компьютере. Этот метод называется реализацией компилятора.
    • Преимущество этого метода заключается в очень быстром выполнении программы после завершения процесса перевода.
    • Большинство производственных реализаций таких языков, как C, COBOL и Ada, созданы компиляторами.

    Процесс компиляции

    • Чистая интерпретация лежит на противоположном конце методов реализации.
    • При таком подходе программы интерпретируются другой программой, называемой интерпретатором, без перевода.
    • Программа-интерпретатор действует как программная имитация машины, цикл выборки-выполнения которой имеет дело с операторами программы языка высокого уровня, а не с машинными инструкциями.
    • Это программное моделирование, очевидно, предоставляет виртуальную машину для языка.
    • Pure Interpretation имеет то преимущество, что позволяет легко реализовать многие операции отладки на уровне исходного кода, поскольку все сообщения об ошибках во время выполнения могут относиться к модулям на уровне исходного кода.
    • С другой стороны, у этого метода есть серьезный недостаток: время выполнения меньше, чем в скомпилированных системах.
    • Основной причиной этой медлительности является декодирование операторов языка высокого уровня, которые намного сложнее, чем инструкции машинного языка.
    • Однако при каждом выполнении оператора его необходимо декодировать. Таким образом, декодирование операторов, а не связь между процессором и памятью, является узким местом чистого интерпретатора.
    • Еще одним недостатком чистой интерпретации является то, что она часто требует больше места. Помимо исходной программы, при интерпретации должна присутствовать таблица символов.
    • Хотя некоторые простые ранние языки 1960-х годов (APL, SNOBOL и LISP) были чисто интерпретируемыми.
    • К 1980-м годам этот подход редко использовался в языках высокого уровня.
    • Однако в последние годы чистая интерпретация значительно вернулась в некоторые языки веб-скриптов, такие как JavaScript и PHP, которые в настоящее время широко используются.

    Гибридные системы внедрения

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

    Гибридная система внедрения

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

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

    Хорошо… но что это на самом деле означает?

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

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

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

    Компилированные языки

    Скомпилированные языки преобразуются непосредственно в машинный код, который может выполнять процессор. В результате они, как правило, выполняются быстрее и эффективнее, чем интерпретируемые языки. Они также дают разработчику больший контроль над аппаратными аспектами, такими как управление памятью и использование ЦП.

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

    Примерами чисто компилируемых языков являются C, C++, Erlang, Haskell, Rust и Go.

    Интерпретируемые языки

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

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

    Примерами распространенных интерпретируемых языков являются PHP, Ruby, Python и JavaScript.

    Небольшое предостережение

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

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

    Преимущества и недостатки

    Преимущества компилируемых языков

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

    Недостатки компилируемых языков

    • Дополнительное время, необходимое для завершения всего шага компиляции перед тестированием.
    • Зависимость сгенерированного двоичного кода от платформы

    Преимущества интерпретируемых языков

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

    Недостатки интерпретируемых языков

    Наиболее заметным недостатком является типичная скорость выполнения по сравнению с скомпилированными языками.

    Если эта статья была вам полезна, отправьте твит .

    Научитесь программировать бесплатно. Учебная программа freeCodeCamp с открытым исходным кодом помогла более чем 40 000 человек получить работу в качестве разработчиков. Начать

    freeCodeCamp – это поддерживаемая донорами некоммерческая организация, освобожденная от налогов в соответствии со статьей 501(c)(3) (идентификационный номер федерального налогоплательщика США: 82-0779546)

    Наша миссия: помочь людям научиться программировать бесплатно. Мы достигаем этого, создавая тысячи видеороликов, статей и интерактивных уроков по кодированию — все они находятся в свободном доступе. У нас также есть тысячи учебных групп freeCodeCamp по всему миру.

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

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

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

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

    Одним из вариантов использования интерпретаторов является выполнение программ на языке высокого уровня. Например, язык программирования Лисп обычно выполняется интерпретатором, а не компилятором. Однако у интерпретаторов есть и другая цель: они могут позволить вам использовать программу на машинном языке, предназначенную для одного типа компьютера, на совершенно другом типе компьютера. Например, одним из первых домашних компьютеров был Commodore 64 или «C64». Хотя вы можете не найти настоящий C64, вы можете найти программы, работающие на других компьютерах или даже в веб-браузере, которые «эмулируют» его. Такой эмулятор может запускать программы C64, выступая в качестве интерпретатора машинного языка C64.

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

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

    Вы можете задаться вопросом, зачем вообще использовать промежуточный байт-код Java? Почему бы просто не распространять исходную программу Java и позволить каждому компилировать ее на машинном языке того компьютера, на котором он хочет ее запускать? Есть несколько причин. Прежде всего, компилятор должен понимать Java, сложный язык высокого уровня. Компилятор сам по себе является сложной программой. Интерпретатор байт-кода Java, с другой стороны, является относительно небольшой и простой программой. Это упрощает написание интерпретатора байт-кода для нового типа компьютера; как только это будет сделано, этот компьютер сможет запускать любую скомпилированную программу Java. Было бы намного сложнее написать компилятор Java для того же компьютера.

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

    Когда Java был еще новым языком, его критиковали за медлительность: поскольку байт-код Java выполнялся интерпретатором, казалось, что программы с байт-кодом Java никогда не смогут работать так же быстро, как программы, скомпилированные на родном машинном языке (т. е. реальный машинный язык компьютера, на котором работает программа). Однако эта проблема была в значительной степени преодолена за счет использования компиляторов точного времени для выполнения байт-кода Java. Своевременный компилятор переводит байт-код Java в машинный язык. Он делает это во время выполнения программы. Так же, как и для обычного интерпретатора, вводом для компилятора JIT является программа байт-кода Java, и его задачей является выполнение этой программы. Но по мере выполнения программы он также переводит ее части на машинный язык. После этого переведенные части программы могут выполняться гораздо быстрее, чем их можно интерпретировать. Поскольку данная часть программы часто выполняется много раз во время работы программы, компилятор "точно в срок" может значительно ускорить общее время выполнения.

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

    В последние несколько лет стало обычным делом создавать новые языки программирования или версии старых языков, которые компилируются в байт-код Java. Скомпилированные программы байт-кода затем могут выполняться стандартной JVM. Новые языки, разработанные специально для программирования JVM, включают Scala, Groovy, Clojure и Processing. Jython и JRuby — это версии старых языков Python и Ruby, предназначенные для JVM. Эти языки позволяют пользоваться многими преимуществами JVM, избегая при этом некоторых технических особенностей языка Java. На самом деле использование других языков с JVM стало настолько важным, что в JVM было добавлено несколько новых функций специально для улучшения поддержки некоторых из этих языков. И это улучшение JVM, в свою очередь, сделало возможным появление некоторых новых функций в Java.

    Я также должен отметить, что действительно сложной частью независимости от платформы является предоставление «графического пользовательского интерфейса» с окнами, кнопками и т. д., который будет работать на всех платформах, поддерживающих Java. Подробнее об этой проблеме вы узнаете в Разделе 1.6.

    Читайте также: