jdk - maquina virtual de java caracteristicas
Máquina Virtual de Java y CLR (5)
CLR y JVM son máquinas virtuales.
.NET Framework y Java Runtime Environment son la agrupación de las respectivas VM y sus bibliotecas. Sin bibliotecas, las máquinas virtuales son bastante inútiles.
Como una especie de seguimiento a la pregunta llamada Diferencias entre MSIL y Java bytecode? , ¿cuál es la (mayor) diferencia o similitud en la forma en que funciona la Máquina Virtual Java frente a cómo funciona .NET Framework Common Language Runtime (CLR) funciona?
Además, es el .NET Framework ¿CLR es una "máquina virtual" o no tiene los atributos de una máquina virtual?
Hay muchas similitudes entre ambas implementaciones (y en mi opinión: sí, ambas son "máquinas virtuales").
En primer lugar, ambas son máquinas virtuales basadas en la pila, sin ninguna noción de "registros" como estamos acostumbrados a ver en una CPU moderna como la x86 o la PowerPC. La evaluación de todas las expresiones ((1 + 1) / 2) se realiza presionando los operandos en la "pila" y sacando esos operandos de la pila cada vez que una instrucción (agregar, dividir, etc.) necesita consumir esos operandos. Cada instrucción devuelve sus resultados a la pila.
Es una forma conveniente de implementar una máquina virtual, ya que casi todas las CPU en el mundo tienen una pila, pero la cantidad de registros suele ser diferente (y algunos registros tienen un propósito especial, y cada instrucción espera sus operandos en diferentes registros, etc. )
Entonces, si vas a modelar una máquina abstracta, un modelo puramente basado en pila es una buena forma de hacerlo.
Por supuesto, las máquinas reales no funcionan de esa manera. Por lo tanto, el compilador JIT es responsable de realizar "enregistration" de las operaciones de bytecode, esencialmente programando los registros de CPU reales para que contengan operandos y resultados siempre que sea posible.
Entonces, creo que esa es una de las características más comunes entre CLR y JVM.
En cuanto a las diferencias ...
Una diferencia interesante entre las dos implementaciones es que CLR incluye instrucciones para crear tipos genéricos y luego aplicar especializaciones paramétricas a esos tipos. Por lo tanto, en tiempo de ejecución, el CLR considera que List <int> es un tipo completamente diferente de List <String>.
Bajo las cubiertas, usa el mismo MSIL para todas las especializaciones de tipo de referencia (por lo que List <String> usa la misma implementación que List <Object>, con diferentes tipos de moldes en los límites de API), pero cada tipo de valor usa su propia implementación única (List <int> genera un código completamente diferente de List <double>).
En Java, los tipos genéricos son un truco puramente de compilación. La JVM no tiene ninguna noción de qué clases tienen argumentos de tipo, y no puede realizar especializaciones paramétricas en el tiempo de ejecución.
Desde una perspectiva práctica, eso significa que no puede sobrecargar los métodos de Java en tipos genéricos. No puede tener dos métodos diferentes, con el mismo nombre, que difieren solo en si aceptan una lista <cadena> o una lista <fecha>. Por supuesto, dado que el CLR conoce los tipos paramétricos, no tiene problemas para manejar métodos sobrecargados en especializaciones de tipo genérico.
En el día a día, esa es la diferencia que noto más entre el CLR y la JVM.
Otras diferencias importantes incluyen:
El CLR tiene cierres (implementados como delegados de C #). La JVM admite cierres solo desde Java 8.
El CLR tiene corrutinas (implementadas con la palabra clave C # ''yield''). La JVM no.
El CLR permite que el código de usuario defina nuevos tipos de valores (estructuras), mientras que la JVM proporciona una colección fija de tipos de valores (byte, corto, int, largo, flotante, doble, char, booleano) y solo permite a los usuarios definir nuevas referencias. tipos (clases).
El CLR proporciona soporte para declarar y manipular punteros. Esto es especialmente interesante porque tanto la JVM como la CLR emplean implementaciones de colector de basura de compactación generacional estrictas como su estrategia de gestión de memoria. En circunstancias normales, un GC de compactación estricta tiene un tiempo realmente difícil con los punteros, porque cuando mueve un valor de una ubicación de memoria a otra, todos los punteros (y punteros a punteros) se vuelven inválidos. Pero el CLR proporciona un mecanismo de "fijación" para que los desarrolladores puedan declarar un bloque de código dentro del cual el CLR no puede mover ciertos punteros. Es muy conveniente.
La unidad más grande de código en la JVM es un ''paquete'' como lo demuestra la palabra clave ''protected'' o posiblemente un JAR (es decir, Java ARchive), como lo demuestra el hecho de poder especificar un jar en classpath y tratarlo como una carpeta de código. En el CLR, las clases se agregan en ''ensambles'', y el CLR proporciona lógica para razonar y manipular ensamblajes (que se cargan en "AppDomains", proporcionando sandboxes a nivel de sub-aplicación para asignación de memoria y ejecución de código).
El formato de código de byte CLR (compuesto de instrucciones MSIL y metadatos) tiene menos tipos de instrucciones que la JVM. En la JVM, cada operación única (agrega dos valores int, agrega dos valores de flotación, etc.) tiene su propia instrucción única. En el CLR, todas las instrucciones MSIL son polimórficas (agregue dos valores) y el compilador JIT es responsable de determinar los tipos de operandos y crear el código de máquina apropiado. Sin embargo, no sé cuál es la estrategia preferible. Ambos tienen intercambios. El compilador HotSpot JIT, para JVM, puede usar un mecanismo de generación de código más simple (no necesita determinar tipos de operandos, porque ya están codificados en la instrucción), pero eso significa que necesita un formato de bytecode más complejo, con más tipos de instrucciones.
He estado usando Java (y admiro la JVM) durante aproximadamente diez años.
Pero, en mi opinión, el CLR es ahora la implementación superior, en casi todos los sentidos.
No es una máquina virtual, el .NET Framework compila los ensamblajes en binario nativo en el momento de la primera ejecución:
En informática, la compilación justo a tiempo (JIT), también conocida como traducción dinámica, es una técnica para mejorar el rendimiento en tiempo de ejecución de un programa informático. JIT se basa en dos ideas anteriores en entornos de tiempo de ejecución: compilación de código byte y compilación dinámica. Convierte código en tiempo de ejecución antes de ejecutarlo de forma nativa, por ejemplo bytecode en código máquina nativo. La mejora del rendimiento sobre los intérpretes se origina al almacenar en caché los resultados de traducir bloques de código, y no simplemente reevaluar cada línea u operando cada vez que se cumple (ver el lenguaje Interpretado). También tiene ventajas sobre la compilación estática del código en el momento del desarrollo, ya que puede recompilar el código si se considera que es ventajoso y puede hacer cumplir las garantías de seguridad. Por lo tanto, JIT puede combinar algunas de las ventajas de la interpretación y la compilación estática (anticipada).
Varios entornos de tiempo de ejecución modernos, como .NET Framework de Microsoft, la mayoría de las implementaciones de Java y, más recientemente, Actionscript 3, se basan en la compilación de JIT para la ejecución de código de alta velocidad.
Fuente: http://en.wikipedia.org/wiki/Just-in-time_compilation
La adición de .NET Framework contiene una máquina virtual, al igual que Java.
Se pueden encontrar más detalles sobre las diferencias en diversas fuentes académicas y privadas. Una vez que un buen ejemplo es CLR Design Choices .
Algunos ejemplos específicos incluyen:
- Algunos opperandos de bajo nivel se escriben como "agregar dos entradas" cuando CLR usa un operando polimórfico. (es decir, fadd / iadd / ladd vs acaba de agregar)
- Actualmente, la JVM realiza perfiles y optimizaciones de tiempo de ejecución más agresivos (es decir, punto de acceso). CLR actualmente realiza optimizaciones JIT, pero no optimiza el tiempo de ejecución (es decir, reemplaza el código mientras está en ejecución).
- CLR no aplica métodos virtuales en línea, JVM sí ...
- Soporte para tipos de valores en el CLR más allá de solo los "primitivos".
Su primera pregunta es comparar JVM con .NET Framework. Supongo que en realidad quería comparar con CLR. Si es así, creo que podrías escribir un pequeño libro sobre esto ( EDITAR: parece que Benji ya tiene :-)
Una diferencia importante es que el CLR está diseñado para ser una arquitectura de lenguaje neutral, a diferencia de la JVM.
Otra diferencia importante es que el CLR se diseñó específicamente para permitir un alto nivel de interoperabilidad con el código nativo. Esto significa que CLR debe administrar la confiabilidad y la seguridad cuando se accede y modifica la memoria nativa, y también se administra la clasificación entre las estructuras de datos basadas en CLR y las estructuras de datos nativas.
Para responder a su segunda pregunta, el término "máquina virtual" es un término anterior del mundo del hardware (por ejemplo, la virtualización de IBM de 360 en la década de 1960) que solía significar una emulación de software / hardware de la máquina subyacente para lograr el mismo tipo de cosas que VMWare hace
El CLR a menudo se conoce como un "motor de ejecución". En este contexto, se trata de una implementación de una IL Machine en la parte superior de un x86. Esto también es lo que hace la JVM, aunque puede argumentar que hay una diferencia importante entre los códigos de byte polimórficos de CLR y los códigos de byte escritos de la JVM.
Entonces, la respuesta pedante a su segunda pregunta es "no". Pero realmente se trata de cómo definir estos dos términos.
EDITAR: Una diferencia más entre la JVM y la CLR es que la JVM (versión 6) es muy reacia a liberar memoria asignada al sistema operativo, incluso donde puede.
Por ejemplo, supongamos que se inicia un proceso de JVM y asigna inicialmente 25 MB de memoria del sistema operativo. El código de la aplicación luego intenta asignaciones que requieren 50 MB adicionales. La JVM asignará 50 MB adicionales del sistema operativo. Una vez que el código de la aplicación ha dejado de usar esa memoria, se recolecta basura y el tamaño del almacenamiento dinámico de la JVM disminuirá. Sin embargo, la JVM solo liberará la memoria del sistema operativo asignada bajo ciertas circunstancias muy específicas . De lo contrario, durante el resto del ciclo de vida del proceso esa memoria permanecerá asignada.
El CLR, por otro lado, libera memoria asignada al sistema operativo si ya no es necesaria. En el ejemplo anterior, el CLR habría liberado la memoria una vez que el montón hubiera disminuido.