MSIL 和 Java 字节码之间的区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/95163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:14:33  来源:igfitidea点击:

Differences between MSIL and Java bytecode?

java.netbytecodecil

提问by user18055

I'm new to .Net and I'm trying to understand the basics first. What is the difference between MSIL and Java bytecode?

我是 .Net 的新手,我想先了解基础知识。MSIL 和 Java 字节码有什么区别?

回答by GHad

There are not that much differences. Both are intermediate formats of the code you wrote. When executed, the Virtual machines will execute the intermediate language managed that means that the Virtual Machine controls the variables and calls. There is even a language which I don't remeber right now that can run at .Net and Java the same way.

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

Basicly, it's just another format for the same thing

基本上,这只是同一件事的另一种格式

Edit: Found the language (besides Scala): It's FAN (http://www.fandev.org/), looks very interesting, but no time yet to evaluate

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

回答by slim

CIL aka MSIL is intended to be human-readable. Java bytecode is not.

CIL 又名 MSIL 旨在使人类可读。Java 字节码不是。

Think of Java bytecode as being machine code for hardware that does not exist (but which JVMs emulate).

将 Java 字节码视为不存在(但 JVM 模拟的硬件)的机器代码。

CIL is more like assembly language - one step from machine code, while still being human-readable.

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

回答by Internet Friend

Agreed, the differences are minute enough to ingore as a beginner. If you want to learn .Net starting from the basics, I'd recommend looking at the Common Language Infrastructure, and the Common Type System.

同意,作为初学者,差异非常小。如果您想从基础开始学习 .Net,我建议您查看公共语言基础结构和公共类型系统。

回答by Jeffrey LeCours

Serge Lidin authored a decent book on the details of MSIL: Expert .NET 2.0 IL Assembler. I also was able to pick up MSIL quickly by looking at simple methods using .NET Reflectorand Ildasm (Tutorial).

Serge Lidin 撰写了一本关于 MSIL 详细信息的不错的书:Expert .NET 2.0 IL Assembler。通过查看使用.NET ReflectorIldasm(教程)的简单方法,我还能够快速掌握 MSIL 。

The concepts between MSIL and Java bytecode are very similar.

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

回答by Guy Starbuck

They are essentially doing the same thing, MSIL is Microsoft's version of Java bytecode.

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

The main differences internally are:

内部的主要区别是:

  1. Bytecode was developed for both compilation and interpretation, while MSIL was developed explicitly for JIT compilation
  2. MSIL was developed to support multiple languages (C# and VB.NET, etc.) versus Bytecode being written for just Java, resulting in Bytecode being more similar to Java syntactically than IL is to any specific .NET language
  3. MSIL has more explicit delineation between value and reference types
  1. 字节码是为编译和解释而开发的,而 MSIL 是为 JIT 编译而开发的
  2. MSIL 的开发是为了支持多种语言(C# 和 VB.NET 等),而字节码只是为 Java 编写的,导致字节码在语法上更类似于 Java,而不是 IL 对任何特定 .NET 语言的相似
  3. MSIL 在值和引用类型之间有更明确的描述

A lot more information and a detailed comparison can be found in this article by K John Gough(postscript document)

更多信息和详细比较可以在K John Gough 的这篇文章(后记文档)中找到

回答by Motti

First off let me say that I don't think that the subtle differences between Java bytecode and MSIL is something that should bother a novice .NET developer. They both serve the same purpose of defining an abstract target machine which is a layer above the physical machine being used in the end.

首先让我说,我不认为 Java 字节码和 MSIL 之间的细微差别应该困扰 .NET 开发新手。它们都用于定义抽象目标机器的相同目的,该抽象目标机器是最终使用的物理机器之上的一层。

MSIL and Java bytecode are very similar, in fact there is a tool called Grasshopperwhich translates MSIL to Java bytecode, I was part of the development team for Grasshopper so I can share a bit of my (faded) knowledge. Please note that I stopped working on this around when .NET framework 2.0 came out so some of these things may not be true any more (if so please leave a comment and I'll correct it).

MSIL 和 Java 字节码非常相似,实际上有一个叫做Grasshopper的工具可以将 MSIL 转换为 Java 字节码,我是 Grasshopper 开发团队的一员,所以我可以分享一些我的(褪色)知识。请注意,当 .NET framework 2.0 出现时,我停止了这个工作,所以其中一些事情可能不再正确(如果是这样,请发表评论,我会更正)。

  • .NET allows user defined types that have value semantics as apposed to the regularreference semantics (struct).
  • .NET supports unsigned types, this makes the instruction set a bit richer.
  • Java includes the exception specification of methods in the bytecode. Although exception specification is usually only enforced by the compiler, it may be enforced by the JVM if a class loader other than the default one is used.
  • .NET generics are expressed in IL while Java generics only use type erasure.
  • .NET attributes have no equivalent in Java (is this still true?).
  • .NET enumsare not much more than wrappers around integer types while Java enumsare pretty much fully fledged classes (thanks to Internet Friendfor commenting).
  • .NET has outand refparameters.
  • .NET 允许用户定义的类型具有与常规引用语义相关的值语义 ( struct)。
  • .NET 支持无符号类型,这使得指令集更丰富一些。
  • Java 在字节码中包含方法的异常规范。尽管异常规范通常仅由编译器强制执行,但如果使用非默认类加载器,则 JVM 可能会强制执行。
  • .NET 泛型用 IL 表示,而 Java 泛型只使用类型擦除
  • .NET 属性在 Java 中没有等价物(这仍然是真的吗?)。
  • .NETenums只不过是整数类型的包装器,而Javaenums几乎是成熟的类(感谢Internet Friend的评论)。
  • .NET 有outref参数。

There are other language differences but most of them are not expressed at the byte code level, for example if memory serves Java's non-staticinner classes (which do not exist in .NET) are not a bytecode feature, the compiler generates an additional argument to the inner class's constructor and passes the outer object. The same is true for .NET lambda expressions.

还有其他语言差异,但大多数都没有在字节码级别表达,例如,如果内存服务 Java 的非static内部类(在 .NET 中不存在)不是字节码功能,编译器会生成一个额外的参数到内部类的构造函数并传递外部对象。.NET lambda 表达式也是如此。

回答by Dennis C

I think MSIL should not compare to Java bytecode, but "the instruction that comprise the Java bytecodes".

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

There is no name of disassembled java bytecode. "Java Bytecode" should be an unofficial alias, as I cannot find its name in official document. The Java Class File Disassemblersay

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

Prints out disassembled code, i.e., the instructions that comprise the Java bytecodes, for each of the methods in the class. These are documented in the Java Virtual Machine Specification.

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

Both "Java VM instructions" and "MSIL" are assembled into .NET bytecode and Java code, which are not human readable.

“Java VM 指令”和“MSIL”都被组装成 .NET 字节码和 Java 代码,它们不是人类可读的。

回答by Justin

CIL(the proper name for MSIL) and Java bytecode are more the same than they are different. There are some important differences though:

CIL(MSIL 的专有名称)和 Java 字节码相同多于不同。但是有一些重要的区别:

1) CIL was designed from the beginning to serve as a target for multiple languages. As such, it supports a much richer type system including signed and unsigned types, value types, pointers, properties, delegates, events, generics, an object-system with a single root, and more. CIL supports features not required for the initial CLR languages (C# and VB.NET) such as global functions and tail-call optimizations. In comparision, Java bytecode was designed as a target for the Java language and reflects many of the constraints found in Java itself. It would be a lot harder to write C or Scheme using Java bytecode.

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

2) CIL was designed to integrate easily into native libraries and unmanaged code

2) CIL 旨在轻松集成到本机库和非托管代码中

3) Java bytecode was designed to be either interpreted or compiled while CIL was designed assuming JIT compilation only. That said, the initial implementation of Monoused an interpreter instead of a JIT.

3) Java 字节码被设计为可以解释或编译,而 CIL 被设计为仅假设 JIT 编译。也就是说,Mono的初始实现使用了解释器而不是 JIT。

4) CIL was designed (and specified) to have a human readable and writable assembly language form that maps directly to the bytecode form. I believe that Java bytecode was (as the name implies) meant to be only machine readable. Of course, Java bytecode is relatively easily decompiled back to the original Java and, as shown below, it can also be "disassembled".

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

I should note that the JVM (most of them) is more highly optimized than the CLR (any of them). So, raw performance might be a reason to prefer targeting Java bytecode. This is an implementation detail though.

我应该注意到 JVM(其中大多数)比 CLR(其中任何一个)都进行了更高程度的优化。因此,原始性能可能是更喜欢以 Java 字节码为目标的原因。不过,这是一个实现细节。

Some people say that the Java bytecode was designed to be multi-platform while CIL was designed to be Windows only. This is not the case. There are some "Windows"isms in the .NET framework but there are none in CIL.

有人说 Java 字节码被设计为多平台的,而 CIL 被设计为仅适用于 Windows。不是这种情况。.NET 框架中有一些“Windows”主义,但 CIL 中没有。

As an example of point number 4) above, I wrote a toy Java to CIL compiler a while back. If you feed this compiler the following Java program:

作为上面第 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 ;
    }
}

my compiler will spit out the following CIL:

我的编译器会吐出以下 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
   }
}

This is a valid CIL program that can be fed into a CIL assembler like ilasm.exeto create an executable. As you can see, CIL is a fully human readable and writable language. You can easily create valid CIL programs in any text editor.

这是一个有效的 CIL 程序,可以像ilasm.exe创建可执行文件一样输入 CIL 汇编程序。如您所见,CIL 是一种完全人类可读和可写的语言。您可以在任何文本编辑器中轻松创建有效的 CIL 程序。

You can also compile the Java program above with the javaccompiler and then run the resulting class files through the javap"disassembler" to get the following:

也可以用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
}

The javapoutput is not compilable (to my knowledge) but if you compare it to the CIL output above you can see that the two are very similar.

javap输出不编译(据我所知),但如果你把它比作CIL输出上面可以看到两个非常相似。