Что делает JVM настолько универсальной, чтобы поддерживать так много языков JVM?

18

JVM поддерживает так много языков, кроме Java, как и Groovy,Clojure,Scalaт. Д., Которые являются функциональными языками в отличие от Java (я имею в виду Java до Версии 8, где Lambda'sони не поддерживаются), которые не поддерживают функциональные возможности. На высоком уровне, что делает JVM настолько универсальной, что она может поддерживать как объектно-ориентированные, так и функциональные языки?

Компьютерщик
источник
"Groovy, Clojure, Scala и т. Д., Которые являются функциональными". Некоторые из них более функциональны, чем другие. Я бы использовал шкалу с Groovy, наименее функциональным и Clojure, со Scala в середине.
Ворг ван Гейр

Ответы:

37

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

Например, до тех пор, пока Java 7 не представила invokedynamicбайт-код, было очень трудно реализовать динамически типизированный ОО-язык на JVM - вам приходилось использовать сложные обходные пути, которые плохо влияли на производительность и приводили к ужасно раздутым следам стека.

И все же до этого в JVM была реализована группа динамических языков (Groovy, Jython, JRuby и др.).

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

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

Майкл Боргвардт
источник
Хороший ответ (+1). Последнее, что вы упомянули, - это IMHO, также ответственный за популярность Java как языка: в конце концов, наличие огромного количества кода, который вы можете повторно использовать бесплатно, может сэкономить вам гораздо больше времени, чем возможность использовать новейший и самый модный язык. функции.
Джорджио
4

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

В Википедии есть список байт-кодов:

http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

а также объяснение того, как JVM загружает байтовые коды:

http://en.wikipedia.org/wiki/Java_virtual_machine

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

sasbury
источник
1
То же самое верно для каждой другой виртуальной машины: YARV Ruby VM, Rubinius Ruby VM, CPython VM (которая в конце концов предшествует JVM), Parrot, различные виртуальные машины Smalltalk и Lisp и, конечно, Pascal P- Система кодирования, после которой моделируется JVM.
Йорг W Mittag
Согласен, JVM определенно не первая виртуальная машина. Я думаю, что JVM популярна для других языков, потому что Java популярна, виртуальная машина активно развивается и хорошо документируется.
Сасбери
2

Я добавлю, что JVM поддерживает четко определенную и довольно приличную модель памяти ( JMM ), что означает хорошую поддержку согласованного (хотя и низкого уровня) поведения потоков. Он также имеет мощный компилятор Just In Time (больше не полезен для динамических языков благодаря MethodHandles и invokedynamic).

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

Мартейн Вербург
источник
JMM - одна из моих наименее любимых вещей о Java. Я фанат эффективно неизменяемых данных (например, массивов, содержимое которых никогда не изменится после того, как они будут видны другим потокам), но с учетом такого утверждения, как someField = new int[]{42};единственные способы гарантировать, что любой поток, который видит новый массив, увидит значение 42 должны либо сделать поле finalили volatile. Если поле генерируется лениво, но к нему часто обращаются, то его создание не finalбудет работать, и его создание volatileможет налагать излишние штрафы за синхронизацию при каждом обращении к нему. Даже в самой свободной модели .NET ...
суперкат
... код может запросить заполнение массива перед сохранением ссылки. Другие потоки, которые читают это поле, могут видеть или не видеть ссылку на новый массив, но сами не будут уверены, что если они увидят новый массив, то увидят его содержимое.
суперкат
1

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

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

Ява тоже не особенная. В Java существование нескольких языков не было даже целью проектирования, в отличие от других виртуальных машин. Для Microsoft .Net CIL способность работать на нескольких языках (C #, VB.Net, ...) была ключевым элементом дизайна, а также ParrotVM из проекта Perl6, предназначенного для создания универсальной виртуальной машины.

Для удовольствия я однажды создал доказательство того, что даже Zend Engine PHP это допустит.

И, честно говоря, в этом нет ничего нового - даже на реальном оборудовании вы можете использовать несколько языков - например, C или Fortran.

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

Johannes
источник
1

JVM - первая из известных мне виртуальных машин, в которой сочетаются сборка мусора, производительность и работоспособная модель песочницы. Появление многих языков для поддержки JVM, вероятно, является не столько результатом его «универсальности», сколько тем, что в языке Java отсутствуют некоторые важные функции, которые нужны людям в языке программирования. Например, хотя большинство машинных языков имеют только полдюжины или около того типов данных (например, байт, полуслово, слово, двойное слово, с плавающей запятой одинарной точности и с плавающей запятой двойной точности), подавляющее большинство языков программирования позволяют использовать код произвольное количество пользовательских типов данных. JVM распознает несколько примитивных типов, аналогичных типам на типичной машине, плюс еще один тип: Ссылка на разнородные объекты. Язык Java также распознает эти примитивы, и беспорядочные ссылки на объекты. Хотя переменная может быть ограничена, чтобы не хранить ссылки на что-либо, что не является конкретным классом, язык не делает различий между любыми из следующих типов полей типаList<String>это может быть проведено MyThingклассом экземпляра MyClass:

  • Ссылка на что-то код знает, что является неизменной реализацией List<String>

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

  • Ссылка на изменяемый список, на который, кроме как во время выполнения MyThingsметодов, никакая другая ссылка не может существовать где-либо в юниверсе.

  • Ссылка на изменяемый список, который принадлежит другому объекту , который этот другой объект хотел бы MyThingиспользовать каким-либо образом.

  • Ссылка на изменчивый список, которому MyThingпринадлежит, но который он также выставил некоторым другим объектам, чтобы они могли что-то с ним сделать.

Хотя все эти поля могут иметь тип List<String>, они содержат разные вещи. Выразительный язык может допускать различие между этими значениями, но Java этого не делает. Поскольку язык может придавать смысл таким вещам (по крайней мере, вне общего контекста) и работать на JVM, это оставляет много места для языков, нацеленных на JVM, для выражения концепций, которые Java не может.

Supercat
источник