La Máquina Da Vinci , también llamada Máquina Virtual Multilenguaje , fue un proyecto de Sun Microsystems cuyo objetivo era crear un prototipo de la extensión de la Máquina Virtual Java (JVM) para añadir soporte para lenguajes dinámicos .
Ya era posible ejecutar lenguajes dinámicos sobre la JVM, pero el objetivo es facilitar la implementación de nuevos lenguajes dinámicos y aumentar su rendimiento. Este proyecto fue la implementación de referencia de JSR 292 ( Compatibilidad con lenguajes con tipos dinámicos en la plataforma Java ). [1]
Antes de Java 7, la máquina virtual Java no tenía soporte integrado para lenguajes tipados dinámicamente :
JSR 292 ( Compatibilidad con lenguajes tipados dinámicamente en la plataforma Java ) [1] propone:
invokedynamic
instrucción a nivel de JVM, para permitir la invocación de métodos basándose en la verificación de tipos dinámica , [3] [4] [5]Tras el éxito de la implementación de JRuby en Java , el proyecto Da Vinci se inició a finales de enero de 2008. [6] Se planeó añadir las capacidades experimentadas por Da Vinci a Java 7. Su objetivo es crear prototipos de este JSR, pero también de otras extensiones de menor prioridad. [7] El primer prototipo funcional, desarrollado como un parche en OpenJDK , se anunció y se puso a disposición a finales de agosto de 2008. [8] [9] [10]
Desde entonces, el equipo de JRuby ha logrado conectar con éxito la invocación dinámica en su código base. La invocación dinámica se entregó con la versión 1.1.5 y se deshabilitará en las JVM sin invokedynamic
capacidades. [11]
Desde entonces, el proyecto se ha integrado en la base de código JDK 7 [12] y luego se ha integrado en la versión Java 7 .
La invocación dinámica se basa en el hecho de que, incluso si Java es un lenguaje fuertemente estático a nivel de lenguaje, la información de tipo es mucho menos frecuente a nivel de código de bytes .
Sin embargo, las implementaciones de lenguajes dinámicos necesitan poder usar compilación en tiempo real (en lugar de reflexión ) para lograr un buen rendimiento y, por lo tanto, compilar scripts en código de bytes en tiempo de ejecución. [ cita requerida ] Para que la máquina virtual Java pueda ejecutarlos , estos códigos de bytes deben verificarse antes de la ejecución y el verificador debe verificar que los tipos sean estáticos en todo el código. Esto lleva a que estas implementaciones tengan que crear muchos códigos de bytes diferentes para los diferentes contextos de una llamada de método, cada vez que cambia la firma de los argumentos .
Esto no solo utiliza mucha memoria, sino que también llena un área de memoria llamada Metaespacio (Generación Permanente anterior a Java 8), una parte del montón que utiliza la JVM para almacenar información sobre las clases . La memoria utilizada en esta área casi nunca se recolecta como basura porque almacena datos inmutables en el contexto de los programas Java; y debido a eso, las implementaciones de lenguajes dinámicos solo pueden compilar una pequeña parte de los scripts. [13]
La JSR 292 propone:
invokedynamic
bytecode que permite a la JVM optimizar llamadas de este tipo. [3]¡Me las arreglé para conectar InvokeDynamic directamente al proceso de envío de JRuby! ¡Qué emoción! El código ya está en el trunk de JRuby y se enviará con JRuby 1.1.5 (aunque obviamente se deshabilitará en las JVM sin InvokeDynamic).
La mayor parte de indy.patch ha ingresado a la máquina virtual JDK7 en el repositorio de integración de mi grupo de trabajo, hoy aproximadamente a las 4:00 a. m. (hora del Pacífico):
El secreto sucio de varias implementaciones de JVM, incluida Hotspot, es que existe un montón separado (o una generación separada del montón) que se utiliza para tipos especiales de datos como definiciones de clase, metadatos de clase y, a veces, código de bytes o código nativo JIT. Y no podría tener un nombre más aterrador: la generación permanente. Excepto en casos raros, los objetos cargados en PermGen nunca se recolectan como basura (porque se supone que son permanentes, ¿lo entiendes?) y, si no se usan con mucho, mucho cuidado, se llenarán(...)