Подтвердить что ты не робот

Почему почти все языки OO компилируются в байт-код?

Из объектно-ориентированных языков, которые я знаю, почти все, кроме С++ и Objective-C, компилируются в байт-код, запущенный на какой-то виртуальной машине. Почему так много разных языков решалось при компиляции в байт-код, в отличие от машинного кода? Возможно ли, чтобы у принцесса был высокоуровневый язык OOP с памятью, который был скомпилирован для машинного кода?

Изменить: я знаю, что поддержка мультиплатформенности часто продвигается как преимущество этого подхода. Однако вполне возможно компилировать изначально на нескольких платформах, не создавая нового компилятора на платформу. Например, можно испустить код C, а затем скомпилировать его с помощью GCC.

4b9b3361

Ответ 1

На самом деле нет причин, это своего рода совпадение. ООП теперь является ведущей концепцией в "большом" программировании, поэтому виртуальные машины.

Также обратите внимание, что есть две отдельные части традиционных виртуальных машин - сборщик мусора и интерпретатор байт-кода/JIT-компилятор, и эти части могут существовать отдельно. Например, реализация Common Lisp под названием SBCL компилирует программу в собственный код, но во время выполнения сильно использует сбор мусора.

Ответ 2

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

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

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

Ответ 3

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

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

Я понятия не имею, почему на языках Microsoft используется байт-код, поскольку для них не важна ни мобильность, ни компактность. Многие мысли, связанные с CLR, вышли из компьютерных ученых в Кембридже, поэтому я предполагаю, что речь идет о простоте анализа и проверки программ.

Обратите внимание, что С++ и Objective C, Eiffel, Ada 9X, Vala и Go - это языки OO (различного урожая), которые скомпилированы непосредственно на собственный код.

В целом, я бы сказал, что OO и байт-код не идут рука об руку. Скорее, мы имеем совпадающую конвергенцию нескольких потоков развития: традиционные интерпретаторы сценариев языков сценариев, таких как Python и Ruby, безумный генеральный план Gosling Java и все, что есть мотивы Microsoft.

Ответ 4

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

foo + bar;

Интерпретатор должен будет сканировать 10 символов, преобразовать их в 4 жетона, построить AST для операции, разрешить три символа (+ - символ, который зависит от типов foo и bar), все, прежде чем он сможет выполнить любое действие, которое фактически зависит от состояния программы во время выполнения. Ничто из этого не может измениться из run to run, и поэтому многие языки пытаются сохранить некоторую форму промежуточного представления.

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

Ответ 5

Bytecode - это значительно более гибкая среда, чем машинный код. Во-первых, он обеспечивает основу для переносимости платформы без необходимости использования компилятора или исходного кода доставки. Поэтому разработчик может распространять одну версию приложения без необходимости отдавать исходный код, требовать сложных инструментов разработчика или предвидеть потенциальные целевые платформы. Хотя позже это не всегда практично, это происходит. Особенно в библиотеках разработчиков говорят, что я распространяю библиотеку, которую я тестировал только в Windows, но кто-то ее использует на Linux или Android. Это происходит довольно часто на самом деле, и большую часть времени он работает, как ожидалось.

Байт-код также, как правило, более оптимизирован, поскольку интерпретатор, потому что он ближе к машинным инструкциям, поэтому быстрее переводится в машинные инструкции. Не все языки OO скомпилированы. Ruby, Python и даже Javascript интерпретируются таким образом, что они не компилируются ни на что, поэтому интерпретатор Ruby должен принимать очень гибкий язык и превращать его в инструкции, но эта гибкость достигается ценой, runtime: анализировать текст, генерировать AST, переводить AST в машинный код и т.д. Также легко сделать оптимизацию, такую ​​как JIT, где байт-код передается непосредственно на машинный код и даже дает возможность для создания оптимизаций для конкретного оборудования.

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

Компиляция OO и байтового кода восходит к 70-м годам с Smalltalk, и я уверен, что кто-то скажет LISP уже в 50-х/60-х годах. Но действительно, только в 90-х годах он начал действительно использоваться в производственных системах в больших масштабах.

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

Ответ 6

В качестве другой точки данных язык программирования D является GC'ed, OO и намного более высоким уровнем, чем С++, все еще компилируется в собственный код.

Ответ 7

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

Ответ 8

Легче разработать интерпретатор, чем компилятор.

Усилия в развитии...:

интерпретатор < байт-код-интерпретатор < bytecode-jit-compiler < язык-компилятор-платформа-независимый язык < Компилятор к множественному машинно-зависимому-ассемблер.

Это общая тенденция, чтобы остановить разработку в jit-компиляторах из-за независимости платформы. Только предпочтительные языки в отношении производительности и исследований в области теоретической информатики разрабатываются и будут разрабатываться во ВСЕХ возможных направлениях, включая новый интерпретатор байт-кода, даже если есть хорошие и продвинутые компиляторы для независимых на платформе языков и для разных машин-зависимых сборщиков.

Исследование на языках ООП довольно... пусть скучно, по сравнению с функциональными языками, потому что действительно новые языки и технологии компилятора более легко выражаются с помощью /in/using математическая теория теории и математические описания гастрольных полных типов, системы. Другими словами: он почти функциональен сам по себе, а императивные языки - это почти только ассемблерные интерфейсы с некоторым синтаксическим сахаром. Языки ООП, как правило, являются обязательными языками, потому что функциональные языки уже закрыты и лямбда. Существуют и другие способы реализации java-подобных "интерфейсов" в функциональных языках, и нет необходимости в дополнительных объектно-ориентированных функциях.

В частности, Haskell, добавление функции OOP-подобного программирования, вероятно, будет более чем на несколько шагов назад в технологии - не было бы смысла использовать это. (< - это не только IMHO... вы когда-нибудь слышали о GADT или классах с несколькими параметрами?) Вероятно, могут быть еще лучшие способы динамического создания объектов с интерфейсами для связи с OOP-languges, чем смены этого языка сам. Но есть и другие функциональные языки, которые явно сочетают функциональные и ООП-аспекты. Существует только больше науки с преимущественно функциональными языками, чем нефункциональные OO-языки.

Языки OO не могут быть легко скомпилированы для других языков OO, если они в некотором роде более "продвинуты". Обычно у них есть такие функции, как защита стека, расширенные возможности отладки, абстрактная и контролируемая многопоточная, динамическая загрузка объектов из файлов из Интернета... Многие из этих функций не являются или нет - легко реализуются с помощью C или С++ в качестве компилятора -backend. Функциональный язык LISP (которому 50 лет!) Был AFAIK первым с сборщиком мусора. Поскольку компилятор-бэкенд LISP использовал взломанную версию языка C, поскольку простая C не разрешала некоторые из этих вещей, ассемблер разрешал, т.е. Правильно-tail-calls или таблицы-next-to-code. C-- позволяет это.

Другой аспект: императивные языки предназначены для работы по определенной архитектуре, то есть программы на C и С++ работают только на тех архитектурах, для которых они запрограммированы. Java более экстремален: он работает только на единой архитектуре, виртуальной, которая сама работает на других. Функциональные языки обычно по дизайну довольно независимы от архитектуры: LISP был разработан так, чтобы быть такой огромной архитектурой, неспецифической, что он может быть скомпилирован в генетический код в ближайшем будущем. Да, как программы, работающие в живых биологических клетках.

При использовании байт-кода для LLVM функциональные языки скорее всего будут скомпилированы в байт-код в будущем. Большинство императивных языков, скорее всего, все же будут иметь те же унаследованные проблемы, что и сейчас, из-за отсутствия абстрагирования - достаточно-достаточно. Ну, я не уверен в том, что касается clang и D, но эти два не являются "самыми" в любом случае.