MSIL 和 Java 字节码的区别?

我是新来的。网络和我试图理解的基本知识第一。MSIL 和 Java 字节码之间的区别是什么?

26182 次浏览

差别不大。两者都是您编写的代码的中间格式。当执行时,虚拟机将执行所管理的中间语言,这意味着虚拟机控制变量和调用。甚至还有一种我现在不记得的语言可以运行。Net 和 Java 的方式是一样的。

基本上,它只是同一事物的另一种格式

编辑: 发现语言(除了 Scala) : 它是 FAN (http://www.fandev.org/) ,看起来很有趣,但是还没有时间来评估

CIL (又名 MSIL)旨在使人类可读,而 Java 字节码则不然。

可以将 Java 字节码看作是硬件的机器代码,这些硬件并不存在(但是 JVM 会模拟它们)。

CIL 更像是汇编语言——离机器代码只有一步之遥,但仍然是人类可读的。

同意,作为一个初学者,这些差异是足够细微的。如果你想学的话。Net 从基础开始,我建议查看公共语言基础结构和公共类型系统。

Serge Lidin 写了一本关于 MSIL 细节的好书: 专家.NET 2.0 IL 汇编程序。我还能够通过查看使用 .NET 反射器Ildasm (教程)的简单方法来快速获取 MSIL。

MSIL 和 Java 字节码之间的概念非常相似。

他们本质上是在做同样的事情,MSIL 是微软版本的 Java 字节码。

内部的主要区别是:

  1. 字节码是为编译和解释而开发的,而 MSIL 则是为 JIT 编译而明确开发的
  2. MSIL 是为了支持多种语言(C # 和 VB. NET 等)而开发的,而字节码只是为 Java 编写的,因此 Bytecode 在语法上与 Java 更相似,而不是与任何特定语言相似。NET 语言
  3. MSIL 在值类型和引用类型之间有更明确的描述

更多的信息和详细的比较可以在 作者: K John Gough(postscript 文档)中找到

首先,我不认为 Java 字节码和 MSIL 之间的细微差别会让新手感到困扰。NET 开发人员。它们都服务于同样的目的,即定义一个抽象目标机器,这个抽象目标机器是最终使用的物理机器之上的一层。

MSIL 和 Java 字节码非常相似,事实上 是一个叫做 蚱蜢的工具,它将 MSIL 翻译成 Java 字节码,我是 Grasshopper 开发团队的一员,所以我可以分享一些我的知识。 请注意,我停止工作的时候。NET 框架2.0出来了,所以这些东西可能不再是真实的(如果是这样,请留下评论,我会纠正它)。

  • NET 允许用户定义的类型具有与 普通的引用语义(struct)相对应的值语义。
  • NET 支持无符号类型,这使指令集更加丰富。
  • Java 包括字节码中方法的异常规范。虽然异常规范通常只由编译器执行,但是如果使用了不同于默认类装入器的类装入器,则异常规范可能由 JVM 执行。
  • .NET 泛型用 IL 表示,而 Java 泛型只使用 类型删除
  • NET 属性在 Java 中没有等价物(现在还是这样吗?)。
  • .NET enums are not much more than wrappers around integer types while Java enums are pretty much fully fledged classes (thanks to 网友 for commenting).
  • NET 具有 outref参数。

还有其他的语言差异,但大多数都不是在字节码级别上表示的,例如,如果内存足够,Java 的非 static内部类(它们不存在于。NET)不是字节码特性,编译器向内部类的构造函数生成一个额外的参数,并传递外部对象。同样的道理也适用于。NET lambda 表达式。

我认为 MSIL 不应该与 Java 字节码相比,而应该是“构成 Java 字节码的指令”。

没有反汇编 Java 字节码的名称。“ Java 字节码”应该是一个非官方的别名,因为我在官方文件中找不到它的名称。 Java 类文件反汇编程序说

为类中的每个方法打印出反汇编代码,即组成 Java 字节码的指令。这些都在 Java 虚拟机规范中有记录。

“ JavaVM 指令”和“ MSIL”都被组装成.NET 字节码和 Java 代码,这是人类无法读取的。

CIL (MSIL 的专有名称)和 Java 字节码更多地是相同的,而不是不同的。不过,两者之间存在一些重要差异:

1) CIL 从一开始就被设计为多种语言的目标。因此,它支持更丰富的类型系统,包括有符号和无符号类型、值类型、指针、属性、委托、事件、泛型、具有单个根的对象系统等。CIL 支持初始 CLR 语言(C # 和 VB.NET)不需要的特性,比如全局函数和 尾部调用优化。相比之下,Java 字节码是作为 Java 语言的目标设计的,它反映了 Java 本身的许多约束。使用 Java 字节码编写 C 或 Scheme 要困难得多。

2) CIL 被设计成易于集成到本地库和非托管代码中

3) Java 字节码设计为解释或编译,CIL 设计为仅进行 JIT 编译。也就是说,单核细胞增多症的最初实现使用了一个解释器而不是 JIT。

4) CIL (并指明)被设计为具有可读和可写的汇编语言形式,直接映射到字节码形式。我相信 Java 字节码(顾名思义)只能是机器可读的。当然,Java 字节码相对容易反编译回原来的 Java,如下所示,它也可以“反汇编”。

我应该注意到,JVM (其中大多数)比 CLR (其中任何一个)更加优化。因此,原始性能可能是更喜欢针对 Java 字节码的一个原因。但这是一个实现细节。

有些人说 Java 字节码被设计成多平台,而 CIL 被设计成仅适用于 Windows。事实并非如此。有一些“视窗”主义。NET 框架,但在 CIL 中没有。

作为上面第四点的一个例子,不久前我写了一个玩具 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 汇编程序(如 ilasm.exe)以创建可执行文件。如您所见,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 输出进行比较,您可以看到两者非常相似。