¿Qué hace que JVM sea tan versátil para admitir tantos lenguajes JVM?

18

JVM admite tantos lenguajes distintos de Java como Groovy,Clojure,Scalaetc., que son lenguajes funcionales a diferencia de Java (me refiero a Java antes de la Versión 8, donde Lambda'sno son compatibles) que no admite capacidades funcionales. En un alto nivel, lo que hace que JVM sea tan versátil que puede admitir lenguajes orientados a objetos y funcionales?

Friki
fuente
"Groovy, Clojure, Scala, etc. que son funcionales". Algunos de ellos son más funcionales que otros. Usaría una escala con Groovy menos funcional y Clojure más, con Scala en el medio.
Vorg van Geir

Respuestas:

37

En comparación con otras máquinas virtuales, la JVM en realidad no es particularmente versátil . Es directamente compatible con OO estáticamente tipado. Para todo lo demás, debe ver qué partes puede usar y cómo puede construir todo lo que su idioma necesita sobre esas partes.

Por ejemplo, hasta que Java 7 introdujo el invokedynamiccódigo de bytes, fue muy difícil implementar un lenguaje OO dinámicamente tipado en la JVM: había que usar soluciones alternativas complejas que eran malas para el rendimiento y resultaban en trazas de pila horriblemente infladas.

Y, sin embargo, se implementaron un montón de lenguajes dinámicos (Groovy, Jython, JRuby, entre otros) en la JVM antes de eso.

No porque la JVM sea tan versátil, sino porque está muy extendida y porque tiene implementaciones muy maduras, bien respaldadas y de alto rendimiento.

Y, quizás aún más importante, porque hay una gran cantidad de código Java que hace casi cualquier cosa, y si su lenguaje se ejecuta en la JVM, puede ofrecer facilidades para integrarse con ese código. Básicamente, tener su idioma ejecutado en JVM es la versión del siglo XXI de ofrecer interoperabilidad con C.

Michael Borgwardt
fuente
Buena respuesta (+1). El último punto que menciona es que, en mi humilde opinión, también es responsable de la popularidad de Java como lenguaje: al final, tener una gran cantidad de código que puede reutilizar de forma gratuita puede ahorrarle mucho más tiempo que poder usar el lenguaje más moderno y moderno caracteristicas.
Giorgio
4

La JVM fue escrita para actuar básicamente como una CPU, hay un conjunto de instrucciones, como un ensamblaje similar, que ejecuta la VM llamada bytecodes. Si puede escribir un compilador que genere un conjunto válido de códigos de bytes, la JVM puede ejecutarlos.

Wikipedia tiene una lista de los códigos de bytes:

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

así como una explicación de cómo la JVM carga los códigos de bytes:

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

Al usar los códigos de byte de estilo de invocación, un lenguaje funcional puede ejecutar código, independientemente de cómo se vea la fuente. Además, con la incorporación de invokevirtual, las implementaciones de lenguaje como jruby han dado cierta flexibilidad con la forma en que se ejecutan.

Sasbury
fuente
1
Lo mismo es cierto para todas las máquinas virtuales: la máquina virtual YARV Ruby, la máquina virtual Rubinius Ruby, la máquina virtual CPython (que, después de todo, es anterior a la JVM), Parrot, varias máquinas virtuales Smalltalk y Lisp, y por supuesto la máquina Pascal P- Sistema de código, después del cual se modela la JVM.
Jörg W Mittag
De acuerdo, la JVM definitivamente no es la primera VM que existe. Creo que la JVM es popular para otros idiomas porque Java es popular, la VM está activamente desarrollada y bien documentada.
sasbury
2

Agregaré que JVM admite un modelo de memoria ( JMM ) bien definido y bastante decente, lo que significa un buen soporte para un comportamiento de subprocesamiento coherente (aunque de bajo nivel). También tiene un poderoso compilador Just In Time (no más útil para lenguajes dinámicos gracias a MethodHandles e invooked Dynamic).

Por último, pero no menos importante, está el subsistema de Recolección de Basura de JVM que (con el ajuste correcto) administra la memoria para usted independientemente del idioma en la parte superior.

Martijn Verburg
fuente
El JMM es una de mis cosas menos favoritas sobre Java. Soy fanático de los datos efectivamente inmutables (por ejemplo, matrices cuyo contenido nunca cambiará después de que sean visibles para otros subprocesos), pero dada una declaración como someField = new int[]{42};las únicas formas de garantizar que cualquier subproceso que vea la nueva matriz vea el valor 42 son para hacer el campo finalo volatile. Si el campo se genera de manera perezosa pero se accede con frecuencia, lo que hace que finalno funcione y que volatileimponga una penalización de sincronización innecesaria cada vez que se accede a él. Incluso en el modelo .NET más flojo ...
supercat
... el código podría solicitar que la población de la matriz ocurra antes del almacén de la referencia. Otros subprocesos que leen el campo pueden o no ver la referencia a la nueva matriz, pero sin costo alguno se asegurarán de que si ven la nueva matriz, verán su contenido.
supercat
1

El elemento clave en esto es la separación de la compilación de la fase de ejecución. Con esto es posible escribir otros compiladores compilando otros idiomas para bytecode.

El código de bytes allí actúa de manera similar al código de máquina de una CPU: tiene todas las pequeñas operaciones necesarias para ejecutar un programa; puede obtener una variable, hacer cálculos matemáticos, operaciones condicionales, etc.

Java tampoco es especial. En Java, la existencia de múltiples idiomas ni siquiera era un objetivo de diseño, a diferencia de otras máquinas virtuales. Para Microsoft .Net CIL, la capacidad de ejecutar múltiples idiomas (C #, VB.Net, ...) fue un elemento de diseño clave, también el ParrotVM del proyecto Perl6 destinado a ser una VM genérica.

Por diversión, una vez creé una prueba de que incluso el motor Zend de PHP lo permitiría.

Y, francamente, esto no es nada nuevo, incluso en hardware real puede ejecutar múltiples idiomas, es decir, C o Fortran.

La diferencia con esta separación de la compilación y la ejecución son los intérpretes clásicos, como algunas formas de Basic, scripts de shell, etc. A menudo funcionan de manera que ejecutan código más o menos línea por línea sin traerlo de forma inmediata. entre.

johannes
fuente
1

La JVM es la primera máquina virtual que conozco que combina recolección de basura, rendimiento y un modelo de caja de arena viable. La aparición de muchos lenguajes para admitir la JVM probablemente no se deba tanto a su "versatilidad", sino al hecho de que el lenguaje Java carece de algunas características importantes que la gente quiere en un lenguaje de programación. Por ejemplo, aunque la mayoría de los lenguajes de máquina tienen solo media docena de tipos de datos (por ejemplo, byte, media palabra, palabra, doble palabra, flotante de precisión simple y flotante de precisión doble), la gran mayoría de los lenguajes de programación permiten el uso de código Un número arbitrario de tipos de datos definidos por el usuario. La JVM reconoce algunos tipos primitivos similares a los de una máquina típica, más un tipo más: la Referencia de objetos promiscuos. El lenguaje Java también reconoce esas primitivas, y referencias de objetos promiscuos. Si bien una variable puede estar restringida a no contener referencias a nada que no sea una clase en particular, el lenguaje no hace distinciones entre ninguno de los siguientes tipos de campo de tipoList<String>que podría tener la MyThingclase de instancia MyClass:

  • Una referencia a algo que el código sabe que es una implementación inmutable de List<String>

  • Una referencia a una instancia de un tipo de lista mutable que nunca estará expuesta a nada que pueda mutarlo.

  • Una referencia a una lista mutable a la cual, excepto durante la ejecución de MyThingslos métodos, no podría existir ninguna otra referencia en ningún lugar del universo.

  • Una referencia a una lista mutable que es propiedad de algún otro objeto , que ese otro objeto le gustaría MyThingusar de alguna manera.

  • Una referencia a una lista mutable que MyThingposee, pero que también ha expuesto a otros objetos para que puedan hacer algo con ella.

Aunque todos esos campos podrían tener tipo List<String>, contienen cosas muy diferentes. Un lenguaje expresivo podría permitir una distinción entre esos significados, pero Java no. Dado que un lenguaje podría atribuir significado a tales cosas (al menos fuera de contextos genéricos) y ejecutarse en la JVM, eso deja mucho espacio para que los lenguajes dirigidos a JVM expresen conceptos que Java no puede.

Super gato
fuente