我是.Net的新手,我想先了解一下基础知识。 MSIL和Java字节码有什么区别?
答案 0 :(得分:71)
首先请允许我说,我认为Java字节码和MSIL之间的细微差别不应该是新手.NET开发人员的烦恼。它们都用于定义抽象目标机器的相同目的,该机器是最终使用的物理机器之上的层。
MSIL和Java字节码非常相似,实际上有一个名为Grasshopper的工具将MSIL转换为Java字节码,我是Grasshopper开发团队的一员,所以我可以分享一些我的(褪色)知识。 请注意,当.NET framework 2.0问世时,我已经停止了这方面的工作,因此其中一些事情可能不再适用(如果是这样,请发表评论,我会更正)。
struct
)相关的值语义。enums
不仅仅是整数类型的包装器,而Java enums
几乎是完全成熟的类(感谢Internet Friend注释)。out
和ref
个参数。还有其他语言差异,但大部分都没有在字节代码级别表达,例如,如果内存服务于Java的非static
内部类(.NET中不存在)不是字节码功能,编译器为内部类的构造函数生成一个附加参数,并传递外部对象。 .NET lambda表达式也是如此。
答案 1 :(得分:22)
他们基本上做同样的事情,MSIL是微软的Java字节码版本。
内部的主要区别是:
可以在this article by K John Gough(postscript文档)
中找到更多信息和详细比较答案 2 :(得分:20)
CIL(MSIL的正确名称)和Java字节码比它们不同的更相同。但是有一些重要的区别:
1)CIL从一开始就被设计为多种语言的目标。因此,它支持更丰富的类型系统,包括有符号和无符号类型,值类型,指针,属性,委托,事件,泛型,具有单个根的对象系统等。 CIL支持初始CLR语言(C#和VB.NET)不需要的功能,例如全局函数和tail-call optimizations。相比之下,Java字节码被设计为Java语言的目标,并反映了Java本身的许多约束。使用Java字节码编写C或Scheme要困难得多。
2)CIL旨在轻松集成到本机库和非托管代码中
3)Java字节码被设计为解释或编译,而CIL的设计仅假设JIT编译。也就是说,Mono的初始实现使用了解释器而不是JIT。
4)CIL被设计为(and specified)以具有人类可读和可写的汇编语言形式,其直接映射到字节码形式。我相信Java字节码(顾名思义)只是机器可读的。当然,Java字节码相对容易反编译回原始Java,如下所示,它也可以“反汇编”。
我应该注意到JVM(大多数)比CLR(其中任何一个)都更加优化。因此,原始性能可能是首选定位Java字节码的原因。这是一个实现细节。
有人说Java字节码设计为多平台,而CIL只设计为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程序,可以输入像ilasm.exe
之类的CIL汇编程序来创建可执行文件。如您所见,CIL是一种完全人类可读写的语言。您可以在任何文本编辑器中轻松创建有效的CIL程序。
您还可以使用javac
编译器编译上面的Java程序,然后通过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
}
javap
输出不可编译(据我所知),但如果将它与上面的CIL输出进行比较,你会发现两者非常相似。
答案 3 :(得分:2)
没有那么多差异。两者都是您编写的代码的中间格式。执行时,虚拟机将执行托管的中间语言,这意味着虚拟机控制变量和调用。甚至还有一种我现在不记得的语言可以同样的方式在.Net和Java上运行。
基本上,它只是同一件事的另一种格式
编辑:找到语言(除了Scala):它是FAN(http://www.fandev.org/),看起来非常有趣,但还没有时间来评估
答案 4 :(得分:2)
CIL aka MSIL旨在使人类可读。 Java字节码不是。
将Java字节码视为不存在的硬件(但是JVM模拟的硬件)的机器代码。
CIL更像汇编语言 - 距机器代码一步,但仍然是人类可读的。
答案 5 :(得分:1)
同意,差异很小,可以作为初学者进入。如果您想从基础知识开始学习.Net,我建议您查看公共语言基础结构和通用类型系统。
答案 6 :(得分:1)
Serge Lidin撰写了一本关于MSIL细节的好书:Expert .NET 2.0 IL Assembler。通过使用.NET Reflector和Ildasm (Tutorial)查看简单方法,我也能够快速获取MSIL。
MSIL和Java字节码之间的概念非常相似。
答案 7 :(得分:1)
我认为MSIL不应该与Java字节码相比,而是“构成Java字节码的指令”。
没有反汇编的java字节码的名称。 “Java字节码”应该是一个非官方的别名,因为我在官方文件中找不到它的名字。 The Java Class File Disassembler说
为类中的每个方法打印出反汇编代码,即组成Java字节码的指令。这些都记录在Java虚拟机规范中。
“Java VM指令”和“MSIL”都汇编成.NET字节码和Java代码,这些都不是人类可读的。