Pregunta

Como una especie de seguimiento de la pregunta llamada ¿Diferencias entre el código de bytes MSIL y Java? , ¿cuáles son las (principales) diferencias o similitudes en el funcionamiento de la Máquina virtual Java en comparación con el .NET Framework Common Language Runtime (CLR)?

Además, es .NET framework CLR a " máquina virtual " o no tiene los atributos de una máquina virtual?

¿Fue útil?

Solución

Hay muchas similitudes entre ambas implementaciones (y en mi opinión: sí, ambas son " máquinas virtuales ").

Por un lado, ambas son máquinas virtuales basadas en pila, sin la noción de " registra " como estamos acostumbrados a ver en una CPU moderna como x86 o PowerPC. La evaluación de todas las expresiones ((1 + 1) / 2) se realiza insertando operandos en & Quot; stack & Quot; y luego sacar 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, porque casi todas las CPU del mundo tienen una pila, pero la cantidad de registros a menudo es diferente (y algunos registros tienen un propósito especial, y cada instrucción espera que sus operandos sean diferentes registros, etc.).

Entonces, si va a modelar una máquina abstracta, un modelo puramente basado en pila es una muy buena manera de hacerlo.

Por supuesto, las máquinas reales no funcionan de esa manera. Por lo tanto, el compilador JIT es responsable de realizar & Quot; enregistration & Quot; de operaciones de código de bytes, esencialmente programando los registros reales de la CPU para contener operandos y resultados siempre que sea posible.

Entonces, creo que ese es uno de los mayores puntos en común entre el CLR y la JVM.

En cuanto a las diferencias ...

Una diferencia interesante entre las dos implementaciones es que el CLR incluye instrucciones para crear tipos genéricos, y luego para aplicar especializaciones paramétricas a esos tipos. Entonces, en tiempo de ejecución, el CLR considera una Lista & Lt; int & Gt; ser un tipo completamente diferente de una Lista < String > ;.

Debajo de las cubiertas, usa el mismo MSIL para todas las especializaciones de tipo de referencia (por lo que una Lista < Cadena > usa la misma implementación que una Lista < Objeto > ;, con diferentes tipos de conversión en los límites de la API), pero cada tipo de valor utiliza su propia implementación única (List < int > genera un código completamente diferente de List < double gt;).

En Java, los tipos genéricos son un truco puramente de compilación. La JVM no tiene idea de qué clases tienen argumentos de tipo, y no puede realizar especializaciones paramétricas en tiempo de ejecución.

Desde una perspectiva práctica, eso significa que no puede sobrecargar los métodos Java en tipos genéricos. No puede tener dos métodos diferentes, con el mismo nombre, que difieren solo en si aceptan una Lista & Lt; String & Gt; 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 tipos genéricos.

En el día a día, esa es la diferencia que más noto entre el CLR y el 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 corutinas (implementadas con la palabra clave 'rendimiento' C #). La JVM no lo hace.

  • 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, short, int, long, float, double, char, boolean) y solo permite usuarios para definir nuevos tipos de referencia (clases).

  • El CLR proporciona soporte para declarar y manipular punteros. Esto es especialmente interesante porque tanto la JVM como el CLR emplean implementaciones estrictas de recolección de basura de compactación generacional como su estrategia de administración de memoria. En circunstancias normales, un GC de compactación estricto tiene dificultades 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 & "; Fijar &"; mecanismo para que los desarrolladores puedan declarar un bloque de código dentro del cual el CLR no puede mover ciertos punteros. Es muy convenientent.

  • La unidad de código más grande en la JVM es un 'paquete' como lo demuestra la palabra clave 'protegida' o podría decirse que es un JAR (es decir, Java ARchive) como puede ser capaz de especificar un jar en el classpath y que sea tratado como una carpeta de código. En el CLR, las clases se agregan en 'ensamblajes', y el CLR proporciona lógica para razonar y manipular ensamblajes (que se cargan en & Quot; AppDomains & Quot ;, proporcionando sandboxes a nivel de sub-aplicación para la asignación de memoria y ejecución de código).

  • El formato de código de bytes CLR (compuesto de instrucciones y metadatos MSIL) tiene menos tipos de instrucciones que la JVM. En la JVM, cada operación única (agregar dos valores int, agregar dos valores flotantes, etc.) tiene su propia instrucción única. En el CLR, todas las instrucciones de 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 compensaciones. El compilador JIT de HotSpot, para JVM, puede usar un mecanismo de generación de código más simple (no necesita determinar los tipos de operandos, porque ya están codificados en la instrucción), pero eso significa que necesita un formato de código de bytes más complejo, con más tipos de instrucciones.

He estado usando Java (y admirando la JVM) durante unos diez años.

Pero, en mi opinión, el CLR ahora es la implementación superior, en casi todos los sentidos.

Otros consejos

Su primera pregunta es comparar JVM con .NET Framework. Supongo que en realidad tenía la intención de comparar con CLR. Si es así, creo que podría 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 fue diseñado específicamente para permitir un alto nivel de interoperabilidad con código nativo. Esto significa que el CLR debe administrar la confiabilidad y la seguridad cuando se accede y modifica la memoria nativa, y también gestionar la clasificación entre estructuras de datos basadas en CLR y estructuras de datos nativas.

Para responder a su segunda pregunta, el término & # 8220; máquina virtual & # 8221; es un término antiguo del mundo del hardware (por ejemplo, la virtualización de IBM & # 8217 del 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 " motor de ejecución " ;. En este contexto, es una implementación de una máquina IL encima 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 bytes polimórficos del CLR y los códigos de bytes escritos de la JVM.

Entonces, la respuesta pedante a su segunda pregunta es " no " ;. Pero realmente se trata de cómo define estos dos términos.

EDITAR: Una diferencia más entre la JVM y la CLR es que la JVM (versión 6) es muy reacio a liberar la memoria asignada al sistema operativo, incluso donde puede.

Por ejemplo, supongamos que se inicia un proceso JVM y asigna inicialmente 25 MB de memoria del sistema operativo. Luego, el código de la aplicación 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 montón JVM disminuirá. Sin embargo, la JVM solo liberará la memoria asignada del sistema operativo bajo ciertas circunstancias muy específicas . De lo contrario, durante el resto del proceso, la memoria permanecerá asignada.

El CLR, por otro lado, libera la 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.

Se pueden encontrar más detalles sobre las diferencias en varias fuentes académicas y privadas. Una vez que un buen ejemplo es CLR Design Choices .

Algunos ejemplos específicos incluyen:

  • Algunos operandos de bajo nivel se escriben como & "; agregue dos ints &"; donde como CLR utiliza un operando polimórfico. (es decir, fadd / iadd / ladd versus solo agregar)
  • Actualmente, la JVM realiza perfiles de optimización y tiempo de ejecución más agresivos (es decir, Hotspot). CLR actualmente realiza optimizaciones JIT, pero no optimiza el tiempo de ejecución (es decir, reemplaza el código mientras se está ejecutando).
  • CLR no integra métodos virtuales, JVM sí ...
  • Soporte para tipos de valor en el CLR más allá de " primitivas " ;.

El CLR y la JVM son máquinas virtuales.

.NET Framework y Java Runtime Environment son la agrupación de las respectivas máquinas virtuales y sus bibliotecas. Sin bibliotecas, las máquinas virtuales son bastante inútiles.

No es una máquina virtual, el marco .net 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 de computadora. JIT se basa en dos ideas anteriores en entornos de tiempo de ejecución: compilación de bytecode y compilación dinámica. Convierte el código en tiempo de ejecución antes de ejecutarlo de forma nativa, por ejemplo, el código de bytes en código máquina nativo. La mejora del rendimiento sobre los intérpretes se origina en el almacenamiento en caché de los resultados de la traducción de bloques de código, y no simplemente en la reevaluación de cada línea u operando cada vez que se cumple (ver Lenguaje interpretado). También tiene ventajas sobre la compilación estática del código en el momento del desarrollo, ya que puede volver a compilar el código si resulta 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 modernos de tiempo de ejecución, 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 JIT para la ejecución de código de alta velocidad.

Fuente: http://en.wikipedia.org/wiki/Just-in -time_compilation

Agregar .NET Framework contiene una máquina virtual, como Java.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top