MSIL 和 Java 字节码之间的区别?
我是 .Net 的新手,我正试图首先了解基础知识。MSIL 和 Java 字节码有什么区别?
我是 .Net 的新手,我正试图首先了解基础知识。MSIL 和 Java 字节码有什么区别?
首先让我说,我不认为Java字节码和MSIL之间的细微差异应该困扰新手.NET开发人员。它们都具有相同的目的,即定义一个抽象的目标机器,该目标机器是最终使用的物理机器之上的一层。
MSIL和Java字节码非常相似,实际上有一个名为Grasshopper的工具,它将MSIL转换为Java字节码,我是Grasshopper开发团队的一员,所以我可以分享一些我(褪色的)知识。请注意,当.NET framework 2.0问世时,我停止了这方面的工作,所以其中一些事情可能不再正确(如果是这样,请发表评论,我会纠正它)。
struct
枚举
几乎是完全成熟的类(感谢Internet Friend的评论)。enums
out
ref
还有其他语言差异,但其中大多数不是在字节码级别表达的,例如,如果内存服务于Java的非内部类(在.NET中不存在)不是字节码功能,编译器会生成一个额外的参数到内部类的构造函数并传递外部对象。.NET lambda 表达式也是如此。static
CIL(MSIL 的专有名称)和 Java 字节码的相同程度大于不同程度。但是,有一些重要的区别:
1)CIL从一开始就被设计为多种语言的目标。因此,它支持更丰富的类型系统,包括有符号和无符号类型、值类型、指针、属性、委托、事件、泛型、具有单个根的对象系统等。CIL 支持初始 CLR 语言(C# 和 VB.NET)不需要的功能,如全局函数和尾部调用优化。相比之下,Java字节码被设计为Java语言的目标,并反映了Java本身的许多约束。使用Java字节码编写C或Scheme会困难得多。
2) CIL 旨在轻松集成到本机库和非托管代码中
3)Java字节码被设计为解释或编译,而CIL的设计假设只有JIT编译。也就是说,Mono的初始实现使用解释器而不是JIT。
4)CIL被设计(并指定)为具有人类可读和可写的汇编语言形式,该形式直接映射到字节码形式。我相信Java字节码(顾名思义)意味着只有机器可读。当然,Java字节码相对容易反编译回原来的Java,如下图所示,它也可以“反汇编”。
我应该注意的是,JVM(大多数)比CLR(其中任何一个)都高度优化。因此,原始性能可能是首选面向 Java 字节码的原因。不过,这是一个实现细节。
有人说Java字节码被设计为多平台,而CIL被设计为仅Windows。事实并非如此。.NET框架中有一些“Windows”主义,但CIL中没有。
作为上面第4点的一个例子,我不久前写了一个玩具Java到CIL编译器。如果向此编译器提供以下 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 ;
}
}
我的编译器将吐出以下 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
}
}
这是一个有效的 CIL 程序,可以馈送到 CIL 汇编程序中,就像创建可执行文件一样。如您所见,CIL是一种完全人类可读和可写的语言。您可以在任何文本编辑器中轻松创建有效的 CIL 程序。ilasm.exe
您还可以使用编译器编译上面的Java程序,然后通过“反汇编器”运行生成的类文件,以获得以下内容:javac
javap
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
}
输出是不可编译的(据我所知),但是如果您将其与上面的CIL输出进行比较,您可以看到两者非常相似。javap