【发布时间】:2010-09-10 20:15:39
【问题描述】:
我是 .Net 新手,我正在尝试先了解基础知识。 MSIL和Java字节码有什么区别?
【问题讨论】:
我是 .Net 新手,我正在尝试先了解基础知识。 MSIL和Java字节码有什么区别?
【问题讨论】:
首先让我说,我不认为 Java 字节码和 MSIL 之间的细微差别会困扰新手 .NET 开发人员。它们都用于定义抽象目标机器的相同目的,该目标机器是最终使用的物理机器之上的一层。
MSIL 和 Java 字节码非常相似,实际上有一个名为 Grasshopper 的工具可以将 MSIL 转换为 Java 字节码,我是 Grasshopper 开发团队的一员,所以我可以分享一些我的(褪色的)知识。 请注意,当 .NET 框架 2.0 出现时,我停止了这方面的工作,因此其中一些事情可能不再正确(如果是这样,请发表评论,我会更正它)。
struct)。enums 只不过是整数类型的包装器,而 Java enums 是非常成熟的类(感谢 Internet Friend 的评论)。out 和ref 参数。还有其他语言差异,但其中大部分没有在字节码级别表示,例如,如果内存服务于 Java 的非static 内部类(在 .NET 中不存在)不是字节码功能,则编译器为内部类的构造函数生成一个附加参数并传递外部对象。 .NET lambda 表达式也是如此。
【讨论】:
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 输出进行比较,您会发现两者非常相似。
【讨论】:
它们本质上是在做同样的事情,MSIL 是微软的 Java 字节码版本。
内部的主要区别是:
更多信息和详细比较可以在this article by K John Gough(后记文档)中找到
【讨论】:
CIL 又名 MSIL 旨在供人类阅读。 Java 字节码不是。
将 Java 字节码视为不存在(但 JVM 模拟)的硬件的机器代码。
CIL 更像是汇编语言 - 与机器代码相距一步,但仍然是人类可读的。
【讨论】:
差别不大。两者都是您编写的代码的中间格式。执行时,虚拟机将执行托管的中间语言,这意味着虚拟机控制变量和调用。甚至还有一种我现在不记得的语言可以以相同的方式在 .Net 和 Java 上运行。
基本上,它只是同一事物的另一种格式
编辑:找到语言(除了 Scala):它是 FAN (http://www.fandev.org/),看起来很有趣,但还没有时间评估
【讨论】:
同意,差异很小,初学者可以理解。如果您想从基础开始学习 .Net,我建议您查看 Common Language Infrastructure 和 Common Type System。
【讨论】:
Serge Lidin 撰写了一本关于 MSIL 细节的不错的书:Expert .NET 2.0 IL Assembler。通过查看使用.NET Reflector 和Ildasm (Tutorial) 的简单方法,我还能够快速掌握MSIL。
MSIL 和 Java 字节码的概念非常相似。
【讨论】:
我认为 MSIL 不应该与 Java 字节码相比,而是“构成 Java 字节码的指令”。
没有反汇编java字节码的名字。 “Java Bytecode”应该是一个非官方的别名,因为我在官方文档中找不到它的名字。 The Java Class File Disassembler说
为类中的每个方法打印出反汇编代码,即组成 Java 字节码的指令。这些都记录在 Java 虚拟机规范中。
“Java VM 指令”和“MSIL”都被组装成 .NET 字节码和 Java 代码,人类不可读。
【讨论】: