Soy nuevo en .Net y estoy tratando de comprender los conceptos básicos primero. ¿Cuál es la diferencia entre MSIL y el código de bytes de Java?
Soy nuevo en .Net y estoy tratando de comprender los conceptos básicos primero. ¿Cuál es la diferencia entre MSIL y el código de bytes de Java?
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
y ref
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.
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 del javap
"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.
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)
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.
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
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.
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.
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.