Articulo de referencia

máquina virtual Java

{{cite web |title=JEP 479: Remove the Windows 32-bit x86 Port |url=https://openjdk.org/jeps/479 |website=OpenJDK}} and JDK 25 (Linux). {{cite web |title=JEP 503: Remove the 32-b...

Descripción general de la arquitectura de una máquina virtual Java (JVM) basada en la especificación de la máquina virtual Java (Java SE 7 Edition).

Una máquina virtual Java ( JVM ) es una máquina virtual que permite a un ordenador ejecutar programas Java , así como programas escritos en otros lenguajes, denominados lenguajes JVM , que también se compilan a bytecode Java . La JVM se describe detalladamente mediante una especificación que detalla los requisitos de su implementación. Contar con esta especificación garantiza la interoperabilidad de los programas Java entre diferentes implementaciones, de modo que los desarrolladores que utilizan el Kit de Desarrollo de Java (JDK) no tengan que preocuparse por las particularidades de la plataforma de hardware subyacente.

La implementación de referencia de la JVM es desarrollada por el proyecto OpenJDK como código abierto e incluye un compilador JIT llamado HotSpot . Las versiones de Java con soporte comercial disponibles de Oracle se basan en el entorno de ejecución OpenJDK. Eclipse OpenJ9 es otra JVM de código abierto para OpenJDK.

Especificación de la JVM

La máquina virtual de Java es un ordenador abstracto (virtual) definido por una especificación. Forma parte del entorno de ejecución de Java (Java Runtime Environment ). El algoritmo de recolección de basura utilizado y cualquier optimización interna de las instrucciones de la máquina virtual de Java (su traducción a código máquina ) no están especificados. La principal razón de esta omisión es no limitar innecesariamente a los implementadores. Cualquier aplicación Java solo puede ejecutarse dentro de una implementación concreta de la especificación abstracta de la máquina virtual de Java. [ 4 ]

A partir de Java Platform, Standard Edition (J2SE) 5.0, se han desarrollado cambios en la especificación de la JVM bajo el Proceso de la Comunidad Java como JSR 924. [ 5 ] A partir de 2006Los cambios en la especificación para admitir los cambios propuestos al formato de archivo de clase (JSR 202) [ 6 ] se están realizando como una versión de mantenimiento de JSR 924. La especificación para la JVM se publicó como el libro azul [ 7 ] , cuyo prefacio establece:

Nuestra intención es que esta especificación documente suficientemente la Máquina Virtual Java para posibilitar implementaciones compatibles en entornos limpios. Oracle proporciona pruebas que verifican el correcto funcionamiento de las implementaciones de la Máquina Virtual Java.

La máquina virtual Java más utilizada es HotSpot de Oracle .

Oracle es propietaria de la marca registrada Java y puede permitir su uso para certificar que los conjuntos de implementación son totalmente compatibles con la especificación de Oracle.

Recolectores de basura

Los recolectores de basura disponibles en la máquina virtual (JVM) de Java OpenJDK incluyen:

  • De serie
  • Paralelo
  • CMS (Barrido de Marcas Concurrente)
  • G1 (Primero la basura)
  • ZGC (Recolector de basura Z)
  • Épsilon
  • Shenandoah
  • GenZGC (ZGC generacional)
  • GenShen (Shenandoah generacional)
  • Metrónomo de IBM (solo en IBM OpenJDK)
  • SAP (solo en SAP OpenJDK)
  • Azul C4 (Recolector de compactación concurrente continua) [ 8 ] (solo en Azul Systems OpenJDK)

La filosofía de diseño de Java gira en torno a la suposición de un recolector de basura. A diferencia de lenguajes como C++ y Rust , la gestión determinista de la memoria a través de una deletepalabra clave (como en C++) no es posible. Incluso introducir tal característica no es posible, debido a la falta de propiedad, aparte de usar sun.misc.Unsafe o a través de java.lang.foreign para asignar/desasignar memoria fuera del montón de Java. [ 9 ] [ 10 ] Debido a que Java usa principalmente la asignación basada en el montón, los objetos se almacenan como referencias y la eliminación resultaría en punteros colgantes .

Foo a = nuevo Foo (); Foo b = a ;eliminar a ; System.out.println ( b ) ;

Arquitectura de máquina virtual

La JVM opera con tipos de datos específicos según lo especificado en las especificaciones de la Máquina Virtual de Java. Los tipos de datos se pueden dividir [ 11 ] en tipos primitivos ( valores enteros y de punto flotante ) y tipos de referencialong . Los doubletipos y , que son de 64 bits , se admiten de forma nativa, pero consumen dos unidades de almacenamiento en las variables locales o la pila de operandos de un marco, ya que cada unidad es de 32 bits. Los tipos boolean, byte, short, y charson todos de extensión de signo (excepto , charque es de extensión de cero ) y se operan como enteros de 32 bits, al igual que intlos tipos . Los tipos más pequeños solo tienen unas pocas instrucciones específicas de tipo para cargar, almacenar y convertir tipos. booleanse opera como bytevalores de 8 bits, donde 0 representa falsey 1 representa true. (Aunque booleanse ha tratado como un tipo desde que la Especificación de la Máquina Virtual Java, Segunda Edición, aclaró este asunto, en el código compilado y ejecutado hay poca diferencia entre un booleany un byteexcepto por la modificación de nombres en las firmas de métodos y el tipo de los arreglos booleanos. booleanLos en las firmas de métodos se modifican como Zmientras que bytelos se modifican como B. Los arreglos booleanos llevan el tipo boolean[]pero usan 8 bits por elemento, y la JVM no tiene capacidad integrada para empaquetar booleanos en un arreglo de bits , por lo que excepto por el tipo, se comportan igual que bytelos arreglos. En todos los demás usos, el booleantipo es efectivamente desconocido para la JVM, ya que todas las instrucciones para operar con booleanos también se usan para operar con byte.)

La JVM dispone de un montón con recolección de basura para almacenar objetos y matrices. El código, las constantes y otros datos de clase se almacenan en el área de métodos. Si bien el área de métodos forma parte lógicamente del montón, las implementaciones pueden tratarla por separado y, por ejemplo, no recolectarla. Cada hilo de la JVM también tiene su propia pila de llamadas (denominada "pila de la máquina virtual Java" para mayor claridad), que almacena marcos . Se crea un nuevo marco cada vez que se llama a un método, y este se destruye cuando finaliza dicho método.

Cada marco proporciona una "pila de operandos" y una matriz de "variables locales". La pila de operandos se utiliza para ejecutar cálculos y para recibir el valor de retorno de un método llamado, mientras que las variables locales cumplen la misma función que los registros y también se utilizan para pasar argumentos a los métodos. Por lo tanto, la JVM es tanto una máquina de pila como una máquina de registros . En la práctica, HotSpot elimina todas las pilas excepto la pila de llamadas/hilos nativa, incluso cuando se ejecuta en modo interpretado, ya que su intérprete de plantillas funciona técnicamente como un compilador.

La JVM utiliza referencias e índices de pila/matriz para acceder a los datos; no utiliza direccionamiento por bytes como la mayoría de las máquinas físicas, por lo que no se ajusta perfectamente a la categorización habitual de máquinas de 32 o 64 bits . En cierto sentido, podría clasificarse como una máquina de 32 bits, ya que este es el tamaño del valor más grande que almacena de forma nativa: un entero o un valor de coma flotante de 32 bits o una referencia de 32 bits. Dado que una referencia tiene 32 bits, cada programa está limitado a un máximo de 2³² referencias únicas y, por lo tanto, a un máximo de 2³² objetos. Sin embargo, cada objeto puede tener más de un byte de tamaño, e incluso ser muy grande; el objeto más grande posible es una matriz de longlongitud 2³¹ - 1 que consumiría 16 GiB de memoria, y podría haber hasta 2³² de estas si hubiera suficiente memoria disponible. Esto da como resultado límites superiores más comparables a los de una máquina típica de 64 bits con direccionamiento por bytes. Una implementación de la JVM puede diseñarse para ejecutarse en un procesador que utilice de forma nativa cualquier ancho de bits, siempre que implemente correctamente las operaciones matemáticas de enteros (8, 16, 32 y 64 bits) y de punto flotante (32 y 64 bits) que requiere la JVM. Dependiendo del método utilizado para implementar las referencias (punteros nativos, punteros comprimidos o una tabla de indirección), esto puede limitar el número de objetos a menos del máximo teórico. Una implementación de la JVM en una plataforma de 64 bits tiene acceso a un espacio de direcciones mucho mayor que una en una plataforma de 32 bits, lo que permite un tamaño de montón mucho mayor y un número máximo de subprocesos mayor, necesario para ciertos tipos de aplicaciones grandes; sin embargo, puede haber una pérdida de rendimiento al usar una implementación de 64 bits en comparación con una de 32 bits.

lenguajes de la JVM

Un lenguaje JVM es cualquier lenguaje con funciones que se pueden expresar en un archivo de clase válido, el cual puede ser alojado por una JVM. Un archivo de clase contiene instrucciones JVM ( código de bytes JVM ), una tabla de símbolos y otra información auxiliar. El formato del archivo de clase es el formato binario independiente del hardware y del sistema operativo que se utiliza para representar clases e interfaces compiladas. [ 12 ]

Existen varios lenguajes para la JVM, tanto lenguajes antiguos y consolidados que se han adaptado a la JVM, como lenguajes mucho más recientes creados desde cero. JRuby y Jython son quizás las adaptaciones más conocidas de lenguajes antiguos, como Ruby y Python , respectivamente. De los nuevos lenguajes creados desde cero para compilarse a bytecode de Java, Clojure , Groovy , Scala y Kotlin son probablemente los más populares. Una característica notable de los lenguajes para la JVM es su interoperabilidad ; son compatibles entre sí, de modo que, por ejemplo, las bibliotecas de Scala se pueden usar con programas Java y viceversa. [ 13 ]

La JVM de Java 7 implementa JSR 292: Soporte para lenguajes de tipado dinámico [ 14 ] en la plataforma Java, una nueva característica que admite lenguajes de tipado dinámico en la JVM. Esta característica se desarrolla dentro del proyecto Da Vinci Machine , cuya misión es extender la JVM para que admita lenguajes distintos de Java. [ 15 ] [ 16 ]

Cargador de clases

Una de las unidades organizativas del código de bytes de la JVM es una clase . Una implementación de cargador de clases debe ser capaz de reconocer y cargar cualquier cosa que cumpla con el formato de archivo de clase de Java . Cualquier implementación puede reconocer otros formatos binarios además de los archivos de clase , pero debe reconocerlos .

El cargador de clases realiza tres actividades básicas en este orden estricto:

  1. Cargando: busca e importa los datos binarios para un tipo
  2. Vinculación: realiza verificación, preparación y (opcionalmente) resolución.
    • Verificación: garantiza la corrección del tipo importado.
    • Preparación: asigna memoria para las variables de clase e inicializa la memoria con valores predeterminados.
    • Resolución: transforma las referencias simbólicas del tipo en referencias directas.
  3. Inicialización: invoca código Java que inicializa las variables de clase con sus valores iniciales adecuados.

En general, existen tres tipos de cargadores de clases: cargador de clases de arranque, cargador de clases de extensión y cargador de clases del sistema/aplicación.

Toda implementación de máquina virtual Java debe contar con un cargador de clases de arranque capaz de cargar clases de confianza, así como un cargador de clases de extensión o de aplicación. La especificación de la máquina virtual Java no indica cómo debe localizar las clases un cargador de clases.

Instrucciones de código de bytes

La JVM tiene instrucciones para los siguientes grupos de tareas:

El objetivo es la compatibilidad binaria. Cada sistema operativo anfitrión requiere su propia implementación de la JVM y su entorno de ejecución. Si bien estas JVM interpretan el código de bytes semánticamente de la misma manera, la implementación real puede ser diferente. Implementar de forma compatible y eficiente la API principal de Java , que debe adaptarse a cada sistema operativo anfitrión, es más complejo que simplemente emular el código de bytes.

Estas instrucciones operan sobre un conjunto de reglas comunes.tipos de datos abstractos en lugar de los tipos de datos nativos de cualquier arquitectura de conjunto de instrucciones específica.

Verificador de código de bytes

Una filosofía básica de Java es su seguridad inherente, ya que ningún programa de usuario puede provocar el bloqueo de la máquina anfitriona ni interferir indebidamente con otras operaciones en ella. Además, permite proteger ciertos métodos y estructuras de datos pertenecientes a código de confianza del acceso o la corrupción por parte de código no confiable que se ejecuta en la misma JVM. Asimismo, impide errores comunes de programación que suelen provocar corrupción de datos o comportamientos impredecibles, como acceder a elementos fuera del rango de un array o usar un puntero no inicializado. Varias características de Java se combinan para proporcionar esta seguridad, incluyendo el modelo de clases, el montón con recolección de basura y el verificador.

La JVM verifica todo el código de bytes antes de su ejecución. Esta verificación consta principalmente de tres tipos de comprobaciones:

  • Las sucursales siempre están en ubicaciones válidas.
  • Los datos siempre se inicializan y las referencias siempre son de tipo seguro.
  • El acceso a datos y métodos privados o de paquetes privados está estrictamente controlado.

Las dos primeras comprobaciones se realizan principalmente durante la fase de verificación que tiene lugar cuando una clase se carga y se habilita para su uso. La tercera se realiza principalmente de forma dinámica, cuando otra clase accede por primera vez a los datos o métodos de una clase.

El verificador solo permite ciertas secuencias de bytecode en programas válidos; por ejemplo, una instrucción de salto (bifurcación) solo puede apuntar a una instrucción dentro del mismo método . Además, el verificador garantiza que cualquier instrucción dada opere en una ubicación de pila fija, [ 17 ] lo que permite al compilador JIT transformar los accesos a la pila en accesos a registros fijos. Debido a esto, el hecho de que la JVM sea una arquitectura de pila no implica una penalización de velocidad para la emulación en arquitecturas basadas en registros cuando se utiliza un compilador JIT. Frente a la arquitectura de la JVM con verificación de código, no hay diferencia para un compilador JIT si obtiene registros imaginarios con nombre o posiciones de pila imaginarias que deben asignarse a los registros de la arquitectura de destino. De hecho, la verificación de código hace que la JVM sea diferente de una arquitectura de pila clásica, cuya emulación eficiente con un compilador JIT es más complicada y generalmente se lleva a cabo con un intérprete más lento. Además, el intérprete utilizado por la JVM predeterminada es un tipo especial conocido como intérprete de plantillas, que traduce el código de bytes directamente a lenguaje de máquina nativo basado en registros en lugar de emular una pila como un intérprete típico. [ 18 ] En muchos aspectos, el intérprete HotSpot puede considerarse un compilador JIT en lugar de un intérprete propiamente dicho, lo que significa que la arquitectura de pila a la que apunta el código de bytes no se utiliza realmente en la implementación, sino que es simplemente una especificación para la representación intermedia que puede implementarse perfectamente en una arquitectura basada en registros. Otro ejemplo de una arquitectura de pila que es simplemente una especificación e implementada en una máquina virtual basada en registros es el Common Language Runtime . [ 19 ]

La especificación original del verificador de código de bytes utilizaba lenguaje natural, el cual era incompleto o incorrecto en algunos aspectos. Se han realizado varios intentos para especificar la JVM como un sistema formal. De esta manera, se puede analizar con mayor profundidad la seguridad de las implementaciones actuales de la JVM y prevenir posibles vulnerabilidades. También será posible optimizar la JVM omitiendo comprobaciones de seguridad innecesarias, si se demuestra que la aplicación en ejecución es segura. [ 20 ]

Ejecución segura de código remoto

Una arquitectura de máquina virtual permite un control muy preciso sobre las acciones que el código dentro de la máquina puede realizar. Presupone que el código es "semánticamente" correcto, es decir, que ha superado con éxito el proceso de verificación de bytecode (formal), materializado por una herramienta, posiblemente externa a la máquina virtual. Esto está diseñado para permitir la ejecución segura de código no confiable de fuentes remotas, un modelo utilizado por los applets de Java y otras descargas de código seguro. Una vez verificado el bytecode, el código descargado se ejecuta en un " sandbox " restringido, diseñado para proteger al usuario de código malicioso o con comportamiento anómalo. Como complemento al proceso de verificación de bytecode, los desarrolladores pueden adquirir un certificado para firmar digitalmente los applets como seguros, lo que les permite solicitar al usuario que salga del sandbox y acceda al sistema de archivos local, al portapapeles , ejecute software externo o se conecte a la red.

La industria de Javacard ha realizado pruebas formales de verificadores de código de bytes (Desarrollo formal de un verificador integrado para el código de bytes de Java Card [ 21 ] ).

Intérprete de código de bytes y compilador Just-in-Time

Para cada arquitectura de hardware se necesita un intérprete de código de bytes de Java diferente . Cuando un ordenador dispone de un intérprete de código de bytes de Java, puede ejecutar cualquier programa en dicho código, y ese mismo programa puede ejecutarse en cualquier ordenador que disponga de dicho intérprete.

Cuando un intérprete ejecuta código de bytes de Java, la ejecución siempre será más lenta que la del mismo programa compilado en lenguaje máquina nativo. Este problema se mitiga con los compiladores Just-In-Time (JIT) para la ejecución de código de bytes de Java. Un compilador JIT puede traducir el código de bytes de Java a lenguaje máquina nativo durante la ejecución del programa. Las partes traducidas del programa se ejecutan mucho más rápido que si se interpretaran. Esta técnica se aplica a las partes del programa que se ejecutan con frecuencia. De esta manera, un compilador JIT puede acelerar significativamente el tiempo total de ejecución.

No existe una conexión necesaria entre el lenguaje de programación Java y el código de bytes de Java. Un programa escrito en Java se puede compilar directamente al lenguaje máquina de una computadora real, y los programas escritos en otros lenguajes distintos de Java se pueden compilar al código de bytes de Java.

El código de bytes de Java está diseñado para ser independiente de la plataforma y seguro. [ 22 ] Algunas implementaciones de JVM no incluyen un intérprete, sino que consisten únicamente en un compilador justo a tiempo. [ 23 ]

Interfaz nativa de Java

La interfaz nativa de Java (o interfaz de método nativo) es un marco de programación de interfaz de función externa (no Java) que permite que el código Java que se ejecuta en una máquina virtual Java (JVM) llame y sea llamado por aplicaciones nativas (programas específicos de una plataforma de hardware y sistema operativo ) y bibliotecas escritas en otros lenguajes como C , C++ y ensamblador .

Java 22 introduce la API de funciones externas y memoria, que puede considerarse la sucesora de la interfaz nativa de Java.

JNI habilita los métodos nativos para gestionar situaciones en las que una aplicación no se puede escribir completamente en el lenguaje de programación Java, por ejemplo, cuando la biblioteca de clases estándar de Java no admite las características específicas de la plataforma o la biblioteca de programas.

El marco de trabajo JNI permite que un método nativo utilice objetos Java del mismo modo que el código Java los utiliza. Un método nativo puede crear objetos Java, inspeccionarlos y utilizarlos para realizar sus tareas. Asimismo, un método nativo puede inspeccionar y utilizar objetos creados por el código de la aplicación Java.

JNI también permite el acceso directo al código ensamblador, sin siquiera pasar por un puente C.[3] Es posible acceder a las aplicaciones Java desde el ensamblador de la misma manera.

JVM en el navegador web

Al comienzo de la vida útil de la plataforma Java, la JVM se comercializó como una tecnología web para crear aplicaciones web enriquecidas . A partir de 2018La mayoría de los navegadores web y los sistemas operativos que incluyen navegadores web no vienen con un complemento de Java , ni permiten la carga lateral de ningún complemento que no sea Flash . El complemento de navegador de Java quedó obsoleto en JDK 9. [ 24 ]

El complemento NPAPI para navegadores Java se diseñó para permitir que la JVM ejecute applets Java integrados en páginas HTML. En los navegadores con el complemento instalado, el applet puede dibujar en una región rectangular de la página. Dado que el complemento incluye una JVM, los applets Java no se limitan al lenguaje de programación Java; cualquier lenguaje compatible con la JVM puede ejecutarse en el complemento. Un conjunto restringido de API permite a los applets acceder al micrófono del usuario o a la aceleración 3D, aunque no pueden modificar la página fuera de su región rectangular. Adobe Flash Player , su principal competidor, funciona de forma similar en este aspecto.

A fecha de junio de 2015Según W3Techs, el uso de applets de Java y Silverlight había caído al 0,1% cada uno para todos los sitios web, mientras que Flash había caído al 10,8%. [ 25 ]

Máquinas virtuales Java (JVM) e intérpretes de JavaScript

Desde mayo de 2016, JavaPoly permite a los usuarios importar bibliotecas Java sin modificar e invocarlas directamente desde JavaScript. JavaPoly permite que los sitios web utilicen bibliotecas Java sin modificar, incluso si el usuario no tiene Java instalado en su ordenador. [ 26 ]

Transpilación a JavaScript

Gracias a las continuas mejoras en la velocidad de ejecución de JavaScript, junto con el creciente uso de dispositivos móviles cuyos navegadores web no admiten complementos, se están realizando esfuerzos para llegar a estos usuarios mediante la transpilación a JavaScript. Es posible transpilar tanto el código fuente como el código de bytes de la JVM a JavaScript.

La compilación del bytecode de la JVM, que es universal en todos los lenguajes de la JVM, permite aprovechar el compilador existente del lenguaje para convertirlo a bytecode. Los principales transpiladores de bytecode de la JVM a JavaScript son TeaVM, [ 27 ] el compilador incluido en Dragome Web SDK, [ 28 ] Bck2Brwsr, [ 29 ] y j2js-compiler. [ 30 ]

Entre los principales transpiladores de lenguajes JVM a JavaScript se incluyen el transpilador Java-to-JavaScript contenido en Google Web Toolkit , J2CL, [ 31 ] Clojurescript (Clojure), GrooScript (Apache Groovy), Scala.js (Scala) y otros. [ 32 ]

Véase también

Notas

  1. Se eliminó la compatibilidad con x86 de 32 bits a partir de JDK 21 (Windows) [ 1 ] y JDK 25 (Linux). [ 2 ]

Referencias

  1. "JEP 479: Eliminar el puerto de Windows de 32 bits x86" . OpenJDK .
  2. "JEP 503: Eliminar el puerto x86 de 32 bits" . OpenJDK .
  3. "JDK 26" .
  4. Bill Venners, Inside the Java Virtual Machine (Archivado el 25/01/2021 en Wayback Machine, Capítulo 5)
  5. "El programa Java Community Process(SM) - JSRs: Java Specification Requests - detalle JSR# 924" . Jcp.org. Archivado del original el 24/12/2020 . Consultado el 26/06/2015 .
  6. "El programa Java Community Process(SM) - JSRs: Java Specification Requests - detalle JSR# 202" . Jcp.org. Archivado del original el 26 de febrero de 2012. Consultado el 26 de junio de 2015 .
  7. La especificación de la máquina virtual Java archivada el 9 de julio de 2008 en Wayback Machine (la primera edición archivada el 12 de octubre de 2008 en Wayback Machine y la segunda edición archivada el 25 de septiembre de 2011 en Wayback Machine también están disponibles en línea).
  8. Tene, Gil; Iyengar, Balaji; Wolf, Michael (2011). "C4: el recolector de compactación concurrente continuo" (PDF) . ISMM '11: Actas del simposio internacional sobre gestión de memoria . doi : 10.1145/1993478 . ISBN 978-1-45030263-0Archivado (PDF) del original el 9 de agosto de 2017 .
  9. Ben Evans (4 de mayo de 2020). "La clase insegura: inseguro a cualquier velocidad" . blogs.oracle.com . Oracle Corporation.
  10. "JEP 454: API de funciones y memoria externas" . OpenJDK. 7 de abril de 2025.
  11. "Capítulo 2. La estructura de la máquina virtual Java" . Archivado del original el 15 de septiembre de 2021. Consultado el 15 de septiembre de 2021 .
  12. "Especificación de la máquina virtual Java: Java SE 7 Edition" (PDF) . Docs.oracle.com. Archivado (PDF) del original el 4 de febrero de 2021. Consultado el 26 de junio de 2015 .
  13. Personal. "Preguntas frecuentes - Interoperabilidad de Java" . scala-lang.org . Archivado del original el 9 de agosto de 2020. Consultado el 18 de noviembre de 2015 .
  14. "El programa Java Community Process(SM) - JSRs: Java Specification Requests - detalle JSR# 292" . Jcp.org. Archivado del original el 20 de diciembre de 2020. Consultado el 26 de junio de 2015 .
  15. "Proyecto Da Vinci Machine" . Openjdk.java.net. Archivado del original el 11 de noviembre de 2020. Consultado el 26 de junio de 2015 .
  16. "Nueva característica de JDK 7: Compatibilidad con lenguajes de tipado dinámico en la máquina virtual Java" . Oracle.com. Archivado del original el 13 de septiembre de 2018. Consultado el 26 de junio de 2015 .
  17. "El proceso de verificación" . Especificación de la máquina virtual Java . Sun Microsystems. 1999. Archivado del original el 21 de marzo de 2011. Consultado el 31 de mayo de 2009 .
  18. "Descripción general del entorno de ejecución de HotSpot - Intérprete" . OpenJDK . Archivado del original el 21/05/2022 . Consultado el 24/05/2021 .
  19. "¿Por qué no hacer que CLR se base en registros? · Problema n.° 4775 · dotnet/runtime" . GitHub . Archivado del original el 20 de abril de 2023. Consultado el 24 de mayo de 2021 .
  20. Freund, Stephen N.; Mitchell, John C. (1999). "Un marco formal para el lenguaje y verificador de bytecode de Java". Actas de la 14.ª conferencia ACM SIGPLAN sobre programación orientada a objetos, sistemas, lenguajes y aplicaciones - OOPSLA '99 . págs. 147–166 . CiteSeerX 10.1.1.2.4663 . doi : 10.1145/320384.320397 . ISBN   978-1581132380. S2CID 14302964 . 
  21. Casset, Ludovic; Burdy, Lilian; Requet, Antoine (10 de abril de 2002). «Desarrollo formal de un verificador integrado para el código de bytes de Java Card» (PDF) . Inria - Instituto Nacional de Investigación en Ciencia y Tecnología Digital de la Universidad de la Costa Azul . Archivado (PDF) del original el 3 de octubre de 2022.
  22. David J. Eck, Introducción a la programación con Java, archivado el 11 de octubre de 2014 en Wayback Machine , séptima edición, versión 7.0, agosto de 2014, sección 1.3 "La máquina virtual de Java".
  23. Introducción a Oracle JRockit Archivado el 6 de septiembre de 2015 en Wayback Machine Versión R28 en 2. "Comprensión de la compilación y optimización Just-In-Time"
  24. "Oracle deja de dar soporte al complemento de navegador Java y se prepara para su desaparición" . Ars Technica . 28 de enero de 2016. Archivado del original el 8 de abril de 2016. Consultado el 15 de abril de 2016 .
  25. "Tendencias anuales históricas en el uso de lenguajes de programación del lado del cliente, junio de 2015" . W3techs.com . Consultado el 26 de junio de 2015 .
  26. Krill, Paul (13 de mayo de 2016). "JavaPoly.js importa código Java existente y lo invoca directamente desde JavaScript" . InfoWorld . Archivado del original el 25 de julio de 2016. Consultado el 18 de julio de 2016 .
  27. "Página principal del proyecto TeaVM" . Teavm.org. Archivado del original el 27 de junio de 2015. Consultado el 26 de junio de 2015 .
  28. "Dragome Web SDK" . Dragome.com. Archivado del original el 1 de agosto de 2015. Consultado el 26 de junio de 2015 .
  29. "Bck2Brwsr - APIDesign" . Wiki.apidesign.org. Archivado del original el 27/06/2015 . Consultado el 26/06/2015 .
  30. Wolfgang Kuehn (decatur). j2js-compiler Archivado el 29/09/2013 en Wayback Machine GitHub
  31. "J2cl: Transpilación de Java a JavaScript para Closure Compiler | Hacker News" . news.ycombinator.com . Archivado del original el 2 de enero de 2021. Consultado el 31 de octubre de 2025 .
  32. "Lista de lenguajes que compilan a JS · jashkenas/coffeescript Wiki · GitHub" . Github.com. 19 de junio de 2015. Archivado del original el 31 de enero de 2020. Consultado el 26 de junio de 2015 .
  • Aclaraciones y enmiendas a la especificación de la máquina virtual Java, segunda edición. Archivado el 10 de enero de 2006 en Wayback Machine. Incluye una lista de cambios que se realizarán para admitir J2SE 5.0 y JSR 45.
  • JSR 45, archivado el 5 de febrero de 2006 en Wayback Machine , especifica cambios en el formato del archivo de clase para admitir la depuración a nivel de código fuente de lenguajes como JavaServer Pages (JSP) y SQLJ que se traducen a Java.
  • Un análisis en profundidad del arranque de la JVM
  • Noticias y opiniones de los miembros del equipo Java de Oracle.
  • Wiki de OpenJDK
  • Blog de Thomas Stüfe - Ingeniero de JVM en Red Hat
  • Recolección de basura de Java simplificada
Obtenido de " https://en.wikipedia.org/w/index.php?title=Java_virtual_machine&oldid=1356517107 "