En primer lugar, déjeme decir que no creo que las sutiles diferencias entre el código de bytes de Java y MSIL sean algo que deba molestar a un desarrollador de .NET novato. Ambos tienen el mismo propósito de definir una máquina objetivo abstracta que es una capa por encima de la máquina física que se utiliza al final.
MSIL y el código de bytes de Java son muy similares, de hecho, hay una herramienta llamada Grasshopper que traduce MSIL al código de bytes de Java, yo era parte del equipo de desarrollo de Grasshopper, así que puedo compartir un poco de mi conocimiento (desvaído). Tenga en cuenta que dejé de trabajar en esto cuando salió .NET framework 2.0, por lo que es posible que algunas de estas cosas ya no sean ciertas (si es así, deje un comentario y lo corregiré).
.NET permite tipos definidos por el usuario que tienen una semántica de valor en oposición a la semántica de referencia regular ( struct).
.NET admite tipos sin firmar, esto hace que el conjunto de instrucciones sea un poco más rico.
Java incluye la especificación de excepción de métodos en el código de bytes. Aunque la especificación de excepciones generalmente solo la aplica el compilador, la JVM puede hacerla cumplir si se usa un cargador de clases diferente al predeterminado.
Los genéricos .NET se expresan en IL, mientras que los genéricos de Java solo usan borrado de tipo .
Los atributos .NET no tienen equivalente en Java (¿sigue siendo así?).
.NET enumsno son mucho más que envoltorios de tipos de enteros, mientras que Javaenums son clases bastante completas (gracias a Internet Friend por sus comentarios).
.NET tiene outy refparámetros.
Hay otras diferencias de lenguaje, pero la mayoría de ellas no se expresan a nivel de código de bytes, por ejemplo, si la memoria sirve a las staticclases no internas de Java (que no existen en .NET) no son una característica de código de bytes , el compilador genera un argumento adicional para el constructor de la clase interna y pasa el objeto externo. Lo mismo ocurre con las expresiones lambda de .NET.
Con respecto a los atributos, las anotaciones de Java se pueden configurar para que aparezcan también en el código de bytes, por lo que hay un equivalente.
Oak
@Oak: las anotaciones de Java solo permiten pasar datos, mientras que los atributos .NET son clases totalmente potenciadas, que pueden tener lógica y, lo más importante, implementar interfaces.
Fyodor Soikin
Bytecode también tiene instrucciones de devolución separadas para cada tipo de devolución, no sé si realmente ayuda en la seguridad de los tipos.
Cecil Lavavajillas
1
El hecho de que los tipos de valor en .NET a veces puedan asignarse en la pila es de importancia trivial en comparación con el hecho de que tienen semántica de valor ; cada ubicación de almacenamiento de tipo valor es una instancia. Por el contrario, cada ubicación de almacenamiento en Java es una referencia de objeto primitiva o promiscua; no hay otros tipos.
supercat
1
¿Se preguntaba cómo se comparan en términos de rendimiento? ¿Es MSIL más rápido de interpretar que el bytecode, por ejemplo?
Luke T O'Brien
23
CIL (el nombre propio de MSIL) y el código de bytes de Java son más iguales que diferentes. Sin embargo, existen algunas diferencias importantes:
1) CIL fue diseñado desde el principio para servir como un objetivo para múltiples idiomas. Como tal, es compatible con un sistema de tipos mucho más rico que incluye tipos firmados y sin firmar, tipos de valor, punteros, propiedades, delegados, eventos, genéricos, un sistema de objetos con una sola raíz y más. CIL admite funciones que no son necesarias para los lenguajes CLR iniciales (C # y VB.NET), como funciones globales y optimizaciones de llamadas finales . En comparación, el código de bytes de Java se diseñó como un objetivo para el lenguaje Java y refleja muchas de las limitaciones que se encuentran en el propio Java. Sería mucho más difícil escribir C o Scheme usando el código de bytes de Java.
2) CIL fue diseñado para integrarse fácilmente en bibliotecas nativas y código no administrado
3) El código de bytes de Java se diseñó para ser interpretado o compilado, mientras que CIL se diseñó asumiendo únicamente la compilación JIT. Dicho esto, la implementación inicial de Mono utilizó un intérprete en lugar de un JIT.
4) CIL fue diseñado ( y especificado ) para tener una forma de lenguaje ensamblador legible y de escritura que se asigna directamente a la forma de código de bytes. Creo que el código de bytes de Java (como su nombre lo indica) estaba destinado a ser solo legible por máquina. Por supuesto, el código de bytes de Java se descompila con relativa facilidad en el Java original y, como se muestra a continuación, también se puede "desensamblar".
Debo señalar que el JVM (la mayoría de ellos) está más optimizado que el CLR (cualquiera de ellos). Por lo tanto, el rendimiento en bruto podría ser una razón para preferir apuntar al código de bytes de Java. Sin embargo, este es un detalle de implementación.
Algunas personas dicen que el código de bytes de Java fue diseñado para ser multiplataforma, mientras que CIL fue diseñado solo para Windows. Este no es el caso. Hay algunos ismos de "Windows" en el marco .NET pero no hay ninguno en CIL.
Como ejemplo del punto número 4) anterior, escribí un compilador de Java para CIL de juguete hace un tiempo. Si alimenta este compilador con el siguiente programa Java:
.assembly extern mscorlib { }
.assembly 'Factorial' { .ver 0:0:0:0 }
.class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object
{
.method publicstaticdefaultvoidmain(string[] a) cil managed
{
.entrypoint
.maxstack 16
newobj instance voidclassFac::'.ctor'()
ldc.i4 3
callvirtinstanceint32classFac::ComputeFac (int32)
callvoidclass [mscorlib]System.Console::WriteLine(int32)
ret
}
}
.classprivateFacextends [mscorlib]System.Object{
.method public instance defaultvoid'.ctor' () cil managed
{
ldarg.0
call instance void object::'.ctor'()
ret
}
.method public int32 ComputeFac(int32 num) cil managed
{
.locals init( int32 num_aux )
ldarg num
ldc.i4 1
clt
brfalse L1
ldc.i4 1
stloc num_aux
br L2
L1:
ldarg num
ldarg.0
ldarg num
ldc.i4 1
sub
callvirt instance int32 class Fac::ComputeFac(int32)
mul
stloc num_aux
L2:
ldloc num_aux
ret
}
}
Este es un programa CIL válido que puede introducirse en un ensamblador CIL como ilasm.exepara crear un ejecutable. Como puede ver, CIL es un lenguaje completamente legible y de escritura. Puede crear fácilmente programas CIL válidos en cualquier editor de texto.
También puede compilar el programa Java anterior con el javaccompilador y luego ejecutar los archivos de clase resultantes a través del javap"desensamblador" para obtener lo siguiente:
Resulta que ha habido intentos de crear un lenguaje ensamblador Java legible / escribible por humanos. Dos que he encontrado son Jasmin y Java Bytecode Assembler
Justin
2
He escrito uno aquí que es mucho mejor. A diferencia de Jasmin, está diseñado para poder desmontar y volver a montar cualquier archivo de clase válido. github.com/Storyyeller/Krakatau . Creo que sería más exacto decir que Microsoft proporciona un ensamblador estándar, mientras que los codificadores de Java tienen que crear el suyo propio.
Antimony
22
Básicamente, están haciendo lo mismo, MSIL es la versión de Microsoft del código de bytes de Java.
Las principales diferencias a nivel interno son:
Bytecode se desarrolló tanto para la compilación como para la interpretación, mientras que MSIL se desarrolló explícitamente para la compilación JIT
MSIL se desarrolló para admitir varios lenguajes (C # y VB.NET, etc.) en lugar de Bytecode que se escribe solo para Java, lo que hace que Bytecode sea más similar a Java sintácticamente que IL a cualquier lenguaje .NET específico
MSIL tiene una delimitación más explícita entre los tipos de valor y referencia
Se puede encontrar mucha más información y una comparación detallada en este artículo de K John Gough (documento posdata)
"1. El código de bytes se desarrolló tanto para la compilación como para la interpretación, mientras que MSIL se desarrolló explícitamente para la compilación JIT". Esto se refiere a cómo el código Java se compila en código de bytes Y ese código de bytes se interpreta. ¿Estoy en lo correcto? ¿MSIL no se interpreta para ejecutarse?
Abdul
2
CIL, también conocido como MSIL, está destinado a ser legible por humanos. El código de bytes de Java no lo es.
Piense en el código de bytes de Java como un código de máquina para hardware que no existe (pero que emulan las JVM).
CIL se parece más al lenguaje ensamblador: un paso del código de máquina, sin dejar de ser legible por humanos.
Bytecode es realmente muy legible siempre que tenga un editor hexadecimal. Es un lenguaje basado en pilas bastante simple con extensiones para la representación directa de clases y métodos. Pensé que MSIL era de nivel inferior (por ejemplo, registros).
Daniel Spiewak
en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… Uno es el CIL sin procesar . El otro es un código de bytes desmontado . El código de bytes puede ser razonablemente legible si asimila hexadecimal, pero ese no es un objetivo de diseño.
delgado
"Desmontado" es realmente la palabra incorrecta. "Descodificado" tal vez. Bytecode es ilegible en los archivos .class simplemente por compacidad. A diferencia de la página de manual de javap, no hay ningún desmontaje involucrado en la producción de un código de bytes legible a partir de una clase compilada.
Daniel Spiewak
2
No hay tantas diferencias. Ambos son formatos intermedios del código que escribió. Cuando se ejecutan, las máquinas virtuales ejecutarán el lenguaje intermedio administrado, lo que significa que la máquina virtual controla las variables y las llamadas. Incluso hay un lenguaje que no recuerdo en este momento que se puede ejecutar en .Net y Java de la misma manera.
Básicamente, es solo otro formato para lo mismo
Editar: Encontré el idioma (además de Scala): Es FAN ( http://www.fandev.org/ ), parece muy interesante, pero aún no hay tiempo para evaluar
Scala se puede compilar para apuntar a JVM o CLR, generando bytecode o MSIL respectivamente.
Daniel Spiewak
Es bueno saberlo, pero encontré otro idioma hace aproximadamente un mes cuando leí DZone: ¡Lo encontré! Ver edición de mi publicación
GHad
1
De acuerdo, las diferencias son lo suficientemente pequeñas como para ignorarlas como principiantes. Si desea aprender .Net a partir de los conceptos básicos, le recomiendo que consulte Common Language Infrastructure y Common Type System.
Creo que MSIL no debería compararse con el código de bytes de Java, sino "la instrucción que comprende los códigos de bytes de Java".
No hay ningún nombre de código de bytes Java desensamblado. "Java Bytecode" debería ser un alias no oficial, ya que no puedo encontrar su nombre en el documento oficial.
El desensamblador de archivos de clase Java dice
Imprime el código desensamblado, es decir, las instrucciones que comprenden los códigos de bytes de Java, para cada uno de los métodos de la clase. Estos están documentados en la Especificación de máquina virtual de Java.
Tanto las "instrucciones Java VM" como "MSIL" se ensamblan en código de bytes .NET y código Java, que no son legibles por humanos.
Respuestas:
En primer lugar, déjeme decir que no creo que las sutiles diferencias entre el código de bytes de Java y MSIL sean algo que deba molestar a un desarrollador de .NET novato. Ambos tienen el mismo propósito de definir una máquina objetivo abstracta que es una capa por encima de la máquina física que se utiliza al final.
MSIL y el código de bytes de Java son muy similares, de hecho, hay una herramienta llamada Grasshopper que traduce MSIL al código de bytes de Java, yo era parte del equipo de desarrollo de Grasshopper, así que puedo compartir un poco de mi conocimiento (desvaído). Tenga en cuenta que dejé de trabajar en esto cuando salió .NET framework 2.0, por lo que es posible que algunas de estas cosas ya no sean ciertas (si es así, deje un comentario y lo corregiré).
struct
).enums
no son mucho más que envoltorios de tipos de enteros, mientras que Javaenums
son clases bastante completas (gracias a Internet Friend por sus comentarios).out
yref
parámetros.Hay otras diferencias de lenguaje, pero la mayoría de ellas no se expresan a nivel de código de bytes, por ejemplo, si la memoria sirve a las
static
clases no internas de Java (que no existen en .NET) no son una característica de código de bytes , el compilador genera un argumento adicional para el constructor de la clase interna y pasa el objeto externo. Lo mismo ocurre con las expresiones lambda de .NET.fuente
CIL (el nombre propio de MSIL) y el código de bytes de Java son más iguales que diferentes. Sin embargo, existen algunas diferencias importantes:
1) CIL fue diseñado desde el principio para servir como un objetivo para múltiples idiomas. Como tal, es compatible con un sistema de tipos mucho más rico que incluye tipos firmados y sin firmar, tipos de valor, punteros, propiedades, delegados, eventos, genéricos, un sistema de objetos con una sola raíz y más. CIL admite funciones que no son necesarias para los lenguajes CLR iniciales (C # y VB.NET), como funciones globales y optimizaciones de llamadas finales . En comparación, el código de bytes de Java se diseñó como un objetivo para el lenguaje Java y refleja muchas de las limitaciones que se encuentran en el propio Java. Sería mucho más difícil escribir C o Scheme usando el código de bytes de Java.
2) CIL fue diseñado para integrarse fácilmente en bibliotecas nativas y código no administrado
3) El código de bytes de Java se diseñó para ser interpretado o compilado, mientras que CIL se diseñó asumiendo únicamente la compilación JIT. Dicho esto, la implementación inicial de Mono utilizó un intérprete en lugar de un JIT.
4) CIL fue diseñado ( y especificado ) para tener una forma de lenguaje ensamblador legible y de escritura que se asigna directamente a la forma de código de bytes. Creo que el código de bytes de Java (como su nombre lo indica) estaba destinado a ser solo legible por máquina. Por supuesto, el código de bytes de Java se descompila con relativa facilidad en el Java original y, como se muestra a continuación, también se puede "desensamblar".
Debo señalar que el JVM (la mayoría de ellos) está más optimizado que el CLR (cualquiera de ellos). Por lo tanto, el rendimiento en bruto podría ser una razón para preferir apuntar al código de bytes de Java. Sin embargo, este es un detalle de implementación.
Algunas personas dicen que el código de bytes de Java fue diseñado para ser multiplataforma, mientras que CIL fue diseñado solo para Windows. Este no es el caso. Hay algunos ismos de "Windows" en el marco .NET pero no hay ninguno en CIL.
Como ejemplo del punto número 4) anterior, escribí un compilador de Java para CIL de juguete hace un tiempo. Si alimenta este compilador con el siguiente programa Java:
class Factorial{ public static void main(String[] a){ System.out.println(new Fac().ComputeFac(10)); } } class Fac { public int ComputeFac(int num){ int num_aux ; if (num < 1) num_aux = 1 ; else num_aux = num * (this.ComputeFac(num-1)) ; return num_aux ; } }
mi compilador escupirá el siguiente CIL:
.assembly extern mscorlib { } .assembly 'Factorial' { .ver 0:0:0:0 } .class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object { .method public static default void main (string[] a) cil managed { .entrypoint .maxstack 16 newobj instance void class Fac::'.ctor'() ldc.i4 3 callvirt instance int32 class Fac::ComputeFac (int32) call void class [mscorlib]System.Console::WriteLine(int32) ret } } .class private Fac extends [mscorlib]System.Object { .method public instance default void '.ctor' () cil managed { ldarg.0 call instance void object::'.ctor'() ret } .method public int32 ComputeFac(int32 num) cil managed { .locals init ( int32 num_aux ) ldarg num ldc.i4 1 clt brfalse L1 ldc.i4 1 stloc num_aux br L2 L1: ldarg num ldarg.0 ldarg num ldc.i4 1 sub callvirt instance int32 class Fac::ComputeFac (int32) mul stloc num_aux L2: ldloc num_aux ret } }
Este es un programa CIL válido que puede introducirse en un ensamblador CIL como
ilasm.exe
para crear un ejecutable. Como puede ver, CIL es un lenguaje completamente legible y de escritura. Puede crear fácilmente programas CIL válidos en cualquier editor de texto.También puede compilar el programa Java anterior con el
javac
compilador y luego ejecutar los archivos de clase resultantes a través deljavap
"desensamblador" para obtener lo siguiente:class Factorial extends java.lang.Object{ Factorial(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: new #3; //class Fac 6: dup 7: invokespecial #4; //Method Fac."<init>":()V 10: bipush 10 12: invokevirtual #5; //Method Fac.ComputeFac:(I)I 15: invokevirtual #6; //Method java/io/PrintStream.println:(I)V 18: return } class Fac extends java.lang.Object{ Fac(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public int ComputeFac(int); Code: 0: iload_1 1: iconst_1 2: if_icmpge 10 5: iconst_1 6: istore_2 7: goto 20 10: iload_1 11: aload_0 12: iload_1 13: iconst_1 14: isub 15: invokevirtual #2; //Method ComputeFac:(I)I 18: imul 19: istore_2 20: iload_2 21: ireturn }
El
javap
resultado no es compilable (que yo sepa) pero si lo compara con el resultado de CIL anterior, puede ver que los dos son muy similares.fuente
Básicamente, están haciendo lo mismo, MSIL es la versión de Microsoft del código de bytes de Java.
Las principales diferencias a nivel interno son:
Se puede encontrar mucha más información y una comparación detallada en este artículo de K John Gough (documento posdata)
fuente
CIL, también conocido como MSIL, está destinado a ser legible por humanos. El código de bytes de Java no lo es.
Piense en el código de bytes de Java como un código de máquina para hardware que no existe (pero que emulan las JVM).
CIL se parece más al lenguaje ensamblador: un paso del código de máquina, sin dejar de ser legible por humanos.
fuente
No hay tantas diferencias. Ambos son formatos intermedios del código que escribió. Cuando se ejecutan, las máquinas virtuales ejecutarán el lenguaje intermedio administrado, lo que significa que la máquina virtual controla las variables y las llamadas. Incluso hay un lenguaje que no recuerdo en este momento que se puede ejecutar en .Net y Java de la misma manera.
Básicamente, es solo otro formato para lo mismo
Editar: Encontré el idioma (además de Scala): Es FAN ( http://www.fandev.org/ ), parece muy interesante, pero aún no hay tiempo para evaluar
fuente
De acuerdo, las diferencias son lo suficientemente pequeñas como para ignorarlas como principiantes. Si desea aprender .Net a partir de los conceptos básicos, le recomiendo que consulte Common Language Infrastructure y Common Type System.
fuente
Serge Lidin es el autor de un libro decente sobre los detalles de MSIL: Expert .NET 2.0 IL Assembler . También pude aprender MSIL rápidamente al observar métodos simples usando .NET Reflector e Ildasm (Tutorial) .
Los conceptos entre MSIL y el código de bytes de Java son muy similares.
fuente
Creo que MSIL no debería compararse con el código de bytes de Java, sino "la instrucción que comprende los códigos de bytes de Java".
No hay ningún nombre de código de bytes Java desensamblado. "Java Bytecode" debería ser un alias no oficial, ya que no puedo encontrar su nombre en el documento oficial. El desensamblador de archivos de clase Java dice
Tanto las "instrucciones Java VM" como "MSIL" se ensamblan en código de bytes .NET y código Java, que no son legibles por humanos.
fuente