quién - ¿Diferencias entre bytecode de MSIL y Java?
tabla de codigo bytecode (8)
Soy nuevo en .Net y estoy tratando de entender lo básico primero. ¿Cuál es la diferencia entre bytecode de MSIL y Java?
Básicamente están haciendo lo mismo, MSIL es la versión de Microsoft de bytecode de Java.
Las principales diferencias internas son:
- Bytecode fue desarrollado para compilación e interpretación, mientras que MSIL fue desarrollado explícitamente para compilación de JIT
- MSIL fue desarrollado para admitir múltiples idiomas (C # y VB.NET, etc.) en comparación con el código de bytes 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 delineación más explícita entre el valor y los tipos de referencia
Se puede encontrar mucha más información y una comparación detallada en este artículo de K John Gough (documento postdata)
CIL también conocido como MSIL está destinado a ser legible por humanos. El bytecode de Java no lo es.
Piense en bytecode Java como código de máquina para hardware que no existe (pero que las JVM emulan).
CIL se parece más al lenguaje ensamblador, a un paso del código de la máquina, al tiempo que sigue siendo legible por el ser humano.
Creo que MSIL no debería comparar con el bytecode de Java, sino con "la instrucción que comprende los códigos de byte de Java".
No hay nombre de bytecode de java desmontado. "Java Bytecode" debería ser un alias no oficial, ya que no puedo encontrar su nombre en el documento oficial. Desensamblador del archivo Java Class
Imprime código desensamblado, es decir, las instrucciones que comprenden los códigos de bytes de Java, para cada uno de los métodos en la clase. Estos están documentados en la especificación de máquina virtual de Java.
Tanto las "instrucciones de Java VM" como las "MSIL" se ensamblan en .NET bytecode y código Java, que no son legibles por humanos.
De acuerdo, las diferencias son lo suficientemente pequeñas como para principiantes. Si desea aprender .Net a partir de lo básico, le recomiendo consultar la Common Language Infrastructure y el Common Type System.
En primer lugar, permítanme decir que no creo que las diferencias sutiles entre bytecode de Java y MSIL sea algo que debería molestar a un desarrollador de .NET novato. Ambas tienen el mismo objetivo de definir una máquina de destino abstracta que es una capa por encima de la máquina física que se utiliza al final.
Los bytecode de MSIL y Java son muy similares, de hecho hay una herramienta llamada Grasshopper que traduce MSIL a bytecode de Java, formé parte del equipo de desarrollo de Grasshopper para poder compartir un poco de mi conocimiento (desvanecido). Tenga en cuenta que dejé de trabajar en esto cuando apareció .NET framework 2.0, por lo que algunas de estas cosas pueden no ser ciertas más (de ser así, dejen un comentario y lo corregiré).
- .NET permite tipos definidos por el usuario que tienen semántica de valores como apposed a la semántica de referencia regular (
struct
). - .NET admite tipos sin firmar, esto hace que las instrucciones sean un poco más ricas.
- Java incluye la especificación de excepción de métodos en bytecode. Aunque la especificación de la excepción generalmente solo es aplicada por el compilador, la JVM puede aplicarla si se utiliza un cargador de clases distinto del 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 (¿esto sigue siendo cierto?).
- Las
enums
.NET no son mucho más que envoltorios alrededor de tipos enteros, mientras que lasenums
Java sonenums
bastante completas (gracias a Internet Friend para comentar). - .NET tiene parámetros de
out
yref
.
Existen otras diferencias de idioma, pero la mayoría no se expresa en el nivel de código de bytes, por ejemplo, si la memoria sirve a las clases internas no static
Java (que no existen en .NET) no son una función de bytecode, el compilador genera un argumento adicional al constructor de la clase interna y pasa el objeto externo. Lo mismo es cierto para las expresiones .NET lambda.
No hay muchas diferencias. Ambos son formatos intermedios del código que usted 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 pueda ejecutarse 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
Serge Lidin es autor de un libro decente sobre los detalles de MSIL: Expert .NET 2.0 IL Assembler . También pude recoger MSIL rápidamente al observar métodos simples usando .NET Reflector e Ildasm (Tutorial) .
Los conceptos entre MSIL y bytecode de Java son muy similares.
CIL (el nombre propio de MSIL) y bytecode de Java son más parecidos de lo que son. Sin embargo, hay 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 tipo mucho más rico que incluye tipos firmados y sin firmar, tipos de valores, punteros, propiedades, delegados, eventos, genéricos, un sistema de objetos con una sola raíz y más. CIL admite funciones no necesarias para los lenguajes iniciales de CLR (C # y VB.NET), como funciones globales y optimizaciones de llamadas de cola . En comparación, Java bytecode se diseñó como un objetivo para el lenguaje Java y refleja muchas de las restricciones encontradas en Java. Sería mucho más difícil escribir C o Scheme usando bytecode de Java.
2) CIL fue diseñado para integrarse fácilmente en bibliotecas nativas y código no administrado
3) Java bytecode fue diseñado para ser interpretado o compilado, mientras que CIL fue diseñado asumiendo solo la compilación de JIT. Dicho esto, la implementación inicial de Mono usó un intérprete en lugar de un JIT.
4) CIL se diseñó ( y se especificó ) para tener un lenguaje de ensamblaje legible y legible por humanos que se asigna directamente al formulario de código de bytes. Creo que el bytecode de Java era (como su nombre lo indica) destinado a ser solo legible por máquina. Por supuesto, el bytecode de Java se descompila con relativa facilidad en el Java original y, como se muestra a continuación, también se puede "desmontar".
Debo señalar que la JVM (la mayoría de ellos) está más optimizada que la CLR (cualquiera de ellos). Por lo tanto, el rendimiento sin procesar puede ser una razón para preferir orientar el bytecode de Java. Sin embargo, este es un detalle de implementación.
Algunas personas dicen que el bytecode de Java fue diseñado para ser multiplataforma, mientras que CIL fue diseñado para ser solo de Windows. Este no es el caso. Hay algunos ismos de "Windows" en el framework .NET pero no hay ninguno en CIL.
Como ejemplo del punto número 4) anterior, escribí hace poco un compilador Java de juguete a CIL. Si le das a este compilador 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 se puede alimentar a un ensamblador CIL como ilasm.exe
para crear un ejecutable. Como puede ver, CIL es un lenguaje totalmente legible y legible por humanos. Puede crear fácilmente programas CIL válidos en cualquier editor de texto.
También puede compilar el programa Java anterior con el compilador javac
y luego ejecutar los archivos de clase resultantes a través del "desensamblador" de javap
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 resultado de javap
no es compilable (que yo sepa) pero si lo comparas con el resultado de CIL anterior, puedes ver que los dos son muy similares.