JVM admite tantos lenguajes distintos de Java como Groovy,Clojure,Scala
etc., que son lenguajes funcionales a diferencia de Java (me refiero a Java antes de la Versión 8, donde Lambda's
no 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?
18
Respuestas:
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
invokedynamic
có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.
fuente
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.
fuente
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.
fuente
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 campofinal
ovolatile
. Si el campo se genera de manera perezosa pero se accede con frecuencia, lo que hace quefinal
no funcione y quevolatile
imponga una penalización de sincronización innecesaria cada vez que se accede a él. Incluso en el modelo .NET más flojo ...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.
fuente
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 tipo
List<String>
que podría tener laMyThing
clase de instanciaMyClass
: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
MyThings
los 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
MyThing
usar de alguna manera.Una referencia a una lista mutable que
MyThing
posee, 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.fuente