MSIL和Java字节码的区别?
我是.Net新手,我想先了解一下基础知识。 MSIL和Java字节码有什么区别?
首先让我说,我不认为Java字节码和MSIL之间的细微差别是应该打扰新手.NET开发人员的东西。 它们都用于定义抽象目标机器的相同目的,抽象目标机器是最后使用的物理机器之上的层。
MSIL和Java字节码非常相似,实际上有一个名为Grasshopper的工具,它将MSIL转换为Java字节码,我是Grasshopper开发团队的一员,所以我可以分享一些我的(淡入)知识。 请注意,当.NET框架2.0出现时,我停止了这个工作,所以这些东西可能不再是真的(如果有的话,请留下评论,我会改正它)。
- .NET允许驻留在堆栈(
struct
)上的用户定义的types。 - .NET支持无符号types,这使得指令集有点更丰富。
- Java包含字节码中方法的exception说明。 虽然exception规范通常只由编译器强制执行,但如果使用除默认类之外的类加载器,则JVM可能会强制执行。
- .NETgenerics以IL表示,而Javagenerics只使用types擦除 。
- .NET中的属性在Java中没有任何对等的(这是真的吗?)。
- .NET
enums
不仅仅是整数types的包装,而Javaenums
几乎是完全成熟的类(感谢Internet Friend的评论)。 - .NET已经
out
和参数。
还有其他的语言差异,但大多数不是在字节代码级别表示,例如,如果内存服务于Java的非static
内部类(不存在于.NET中)不是字节码function,则编译器会生成额外的参数到内部类的构造函数并传递外部对象。 .NET lambdaexpression式也是如此。
他们本质上是做同样的事情,MSIL是微软版本的Java字节码。
内部的主要差异是:
- 字节码是为编译和解释而开发的,而MSIL是为JIT编译明确开发的
- MSIL是为支持多种语言(C#和VB.NET等)而开发的,而Bytecode只是为Java编写的,导致Bytecode在语法上更类似于Java,而IL则是针对任何特定的.NET语言
- MSIL在值和引用types之间有更明确的界定
K John Gough (postscript文档)在这篇文章中可以find更多的信息和详细的比较。
CIL (MSIL的专有名称)和Java字节码比它们不同。 虽然有一些重要的区别:
1)CIL从一开始就被devise为多语言的目标。 因此,它支持更加丰富的types系统,包括带符号和无符号types,值types,指针,属性,委托,事件,generics,具有单个根的对象系统等等。 CIL支持初始CLR语言(C#和VB.NET)不需要的function,如全局函数和尾部调用优化 。 相比之下,Java字节码被devise为Java语言的目标,并反映了Java本身中的许多约束。 使用Java字节码编写C或Scheme将会困难得多。
2)CIL被devise成可以很容易地集成到本地库和非托pipe代码中
3)Java字节码被devise为被解释或编译,而CIL被devise成只假定JIT编译。 也就是说, Mono的初始实现使用了一个解释器而不是JIT。
4)CIL被devise( 并指定 )具有人类可读和可写汇编语言forms,直接映射到字节码forms。 我相信Java字节码(顾名思义)就是只能是机器可读的。 当然,Java字节码相对容易反编译回原来的Java,如下图所示,它也可以被“反汇编”。
我应该注意到,JVM(其中大多数)比CLR(其中任何一个)都更加优化。 所以,原始性能可能是select目标Java字节码的一个理由。 尽pipe这是一个实现细节。
有人说Java字节码被devise成多平台,而CIL被devise成只有Windows。 不是这种情况。 在.NET框架中有一些“Windows”主题,但在CIL中没有。
作为上述第4)点的一个例子,我刚才给CIL编译器写了一个玩具Java。 如果您为此编译器提供以下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程序,可以input到像ilasm.exe
这样的CIL汇编程序来创build一个可执行文件。 正如你所看到的,CIL是一种完全人类可读和可写的语言。 您可以在任何文本编辑器中轻松创build有效的CIL程序。
您也可以使用javac
编译器编译上面的Java程序,然后通过javap
“disassembler”运行生成的类文件以获得以下内容:
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 }
javap
输出是不可编译的(据我所知),但是如果你把它和上面的CIL输出进行比较,你可以看到两者非常相似。
CIL又名MSIL旨在是人类可读的。 Java字节码不是。
把Java字节码看作是不存在的硬件的机器码(但是JVM模拟的)。
CIL更像汇编语言 – 离机器代码仅一步之遥,同时仍然是人类可读的。
没有太大的差异。 两者都是您编写的代码的中间格式。 当执行时,虚拟机将执行pipe理的中间语言,这意味着虚拟机控制variables和调用。 甚至有一种我现在不记得的语言,可以用.Net和Java以同样的方式运行。
基本上,这只是另一种相同的格式
编辑:find语言(除了斯卡拉):这是风扇( http://www.fandev.org/ ),看起来很有趣,但没有时间去评估
同意,差异足够作为一个初学者ing ing。 如果你想从基础知识开始学习.Net,我build议你看一下Common Language Infrastructure和Common Type System。
Serge Lidin撰写了一本关于MSIL: Expert .NET 2.0 IL Assembler细节的书籍。 我也可以通过使用.NET Reflector和Ildasm(教程)的简单方法快速获取MSIL。
MSIL和Java字节码之间的概念非常相似。
我认为MSIL不应该与Java字节码进行比较,而是“构成Java字节码的指令”。
没有反汇编的java字节码的名字。 “Java Bytecode”应该是一个非官方的别名,因为我在官方文档中找不到它的名字。 Java类文件反汇编说
为类中的每个方法打印反汇编的代码,即组成Java字节码的指令。 这些logging在Java虚拟机规范中。
“Java VM指令”和“MSIL”都被组合成.NET字节码和Java代码,这些代码不可读。