Sự khác biệt giữa MSIL và Java bytecode?


Câu trả lời:


75

Trước hết, hãy để tôi nói rằng tôi không nghĩ rằng sự khác biệt nhỏ giữa Java bytecode và MSIL là điều gì đó khiến một nhà phát triển .NET mới làm quen với nó phải bận tâm. Cả hai đều phục vụ cùng một mục đích là xác định một máy đích trừu tượng là một lớp phía trên máy vật lý đang được sử dụng cuối cùng.

MSIL và Java bytecode rất giống nhau, trên thực tế có một công cụ tên là Grasshopper dịch MSIL sang Java bytecode, tôi là thành viên của nhóm phát triển Grasshopper nên tôi có thể chia sẻ một chút kiến ​​thức (còn mờ nhạt) của mình. Xin lưu ý rằng tôi đã ngừng làm việc này vào khoảng thời gian .NET framework 2.0 ra mắt nên một số điều này có thể không còn đúng nữa (nếu có, vui lòng để lại nhận xét và tôi sẽ sửa lại).

  • .NET cho phép các kiểu do người dùng xác định có ngữ nghĩa giá trị được thêm vào ngữ nghĩa tham chiếu thông thường ( struct).
  • .NET hỗ trợ các kiểu không dấu, điều này làm cho tập lệnh phong phú hơn một chút.
  • Java bao gồm đặc tả ngoại lệ của các phương thức trong mã bytecode. Mặc dù đặc tả ngoại lệ thường chỉ được thực thi bởi trình biên dịch, nhưng nó có thể được thực thi bởi JVM nếu một trình tải lớp khác với trình tải mặc định được sử dụng.
  • Các phần tử chung .NET được thể hiện bằng IL trong khi các phần tử chung của Java chỉ sử dụng tính năng xóa kiểu .
  • Các thuộc tính .NET không có tương đương trong Java (điều này có còn đúng không?).
  • .NET enumskhông hơn nhiều so với các lớp bao bọc xung quanh các kiểu số nguyên trong khi Javaenums là các lớp chính thức khá nhiều (cảm ơn Internet Friend đã nhận xét).
  • .NET có outrefcác tham số.

Có những khác biệt về ngôn ngữ khác nhưng hầu hết chúng không được thể hiện ở cấp mã byte, ví dụ: nếu bộ nhớ phục vụ các staticlớp không phải bên trong của Java (không tồn tại trong .NET) không phải là một tính năng bytecode, thì trình biên dịch sẽ tạo một đối số bổ sung để phương thức khởi tạo của lớp bên trong và chuyển đối tượng bên ngoài. Điều này cũng đúng với biểu thức .NET lambda.


Về thuộc tính - Các chú thích Java cũng có thể được thiết lập để xuất hiện trong mã bytecode, do đó, có một tương đương.
Oak,

@Oak: Các chú thích của Java chỉ cho phép truyền dữ liệu, trong khi các thuộc tính .NET là các lớp được cung cấp đầy đủ, có thể có logic và quan trọng nhất là triển khai các giao diện.
Fyodor Soikin

Bytecode cũng có các hướng dẫn trả về riêng biệt cho mọi loại kiểu trả về, dunno nếu nó thực sự hỗ trợ an toàn cho kiểu.
Máy rửa bát Cecil

1
Thực tế là các kiểu giá trị trong .NET đôi khi có thể được phân bổ trên ngăn xếp có tầm quan trọng nhỏ so với thực tế là chúng có ngữ nghĩa giá trị ; mọi vị trí lưu trữ kiểu giá trị một phiên bản. Ngược lại, mọi vị trí lưu trữ trong Java đều là một tham chiếu đối tượng nguyên thủy hoặc lăng nhăng; không có loại nào khác.
supercat

1
Có phải tự hỏi làm thế nào họ so sánh hiệu suất khôn ngoan? MSIL có nhanh hơn để giải thích sau đó bytecode chẳng hạn?
Luke T O'Brien

23

CIL (tên riêng của MSIL) và mã bytecode của Java giống nhau hơn là chúng khác nhau. Tuy nhiên, có một số khác biệt quan trọng:

1) CIL được thiết kế ngay từ đầu để phục vụ như một mục tiêu cho nhiều ngôn ngữ. Do đó, nó hỗ trợ một hệ thống kiểu phong phú hơn nhiều bao gồm các kiểu có dấu và không dấu, kiểu giá trị, con trỏ, thuộc tính, đại biểu, sự kiện, tổng thể, hệ thống đối tượng có một gốc duy nhất, v.v. CIL hỗ trợ các tính năng không cần thiết cho các ngôn ngữ CLR ban đầu (C # và VB.NET) chẳng hạn như các chức năng toàn cục và tối ưu hóa cuộc gọi đuôi . Để so sánh, Java bytecode được thiết kế như một mục tiêu cho ngôn ngữ Java và phản ánh nhiều ràng buộc được tìm thấy trong chính Java. Sẽ khó hơn rất nhiều để viết C hoặc Scheme bằng Java bytecode.

2) CIL được thiết kế để tích hợp dễ dàng vào các thư viện gốc và mã không được quản lý

3) Mã bytecode của Java được thiết kế để có thể thông dịch hoặc biên dịch trong khi CIL được thiết kế với giả định chỉ biên dịch JIT. Điều đó nói rằng, việc triển khai Mono ban đầu sử dụng một trình thông dịch thay vì một JIT.

4) CIL được thiết kế ( và được chỉ định ) để có một dạng ngôn ngữ hợp ngữ có thể đọc và ghi được của con người, ánh xạ trực tiếp tới dạng bytecode. Tôi tin rằng mã bytecode của Java (như tên của nó) có nghĩa là chỉ máy có thể đọc được. Tất nhiên, Java bytecode tương đối dễ dàng được dịch ngược trở lại Java gốc và như hình dưới đây, nó cũng có thể được "tháo rời".

Tôi nên lưu ý rằng JVM (hầu hết trong số chúng) được tối ưu hóa cao hơn CLR (bất kỳ trong số chúng). Vì vậy, hiệu suất thô có thể là một lý do để thích nhắm mục tiêu theo mã byte Java. Đây là một chi tiết thực hiện mặc dù.

Một số người nói rằng mã bytecode của Java được thiết kế để đa nền tảng trong khi CIL được thiết kế chỉ dành cho Windows. Đây không phải là trường hợp. Có một số isms "Windows" trong .NET framework nhưng không có trong CIL.

Như ví dụ của điểm số 4) ở trên, tôi đã viết một trình biên dịch Java sang CIL đồ chơi một thời gian trước. Nếu bạn cung cấp trình biên dịch này chương trình Java sau:

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 ;
    }
}

trình biên dịch của tôi sẽ tạo ra CIL sau:

.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
   }
}

Đây là một chương trình CIL hợp lệ có thể được đưa vào một trình hợp dịch CIL như ilasm.exeđể tạo một tệp thực thi. Như bạn có thể thấy, CIL là một ngôn ngữ hoàn toàn có thể đọc và ghi được của con người. Bạn có thể dễ dàng tạo các chương trình CIL hợp lệ trong bất kỳ trình soạn thảo văn bản nào.

Bạn cũng có thể biên dịch chương trình Java ở trên bằng javactrình biên dịch và sau đó chạy các tệp lớp kết quả thông qua javap"trình tháo gỡ" để có được những điều sau:

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
}

Đầu javapra không thể biên dịch được (theo hiểu biết của tôi) nhưng nếu bạn so sánh nó với đầu ra CIL ở trên, bạn có thể thấy rằng cả hai rất giống nhau.


2
Hóa ra đã có những nỗ lực để tạo ra một ngôn ngữ hợp ngữ Java có thể đọc / ghi được của con người. Hai mà tôi đã tìm thấy là JasminJava bytecode Assembler
Justin

2
Tôi đã viết một ở đây tốt hơn nhiều. Không giống như Jasmin, nó được thiết kế để có thể tháo rời và lắp ráp lại bất kỳ tệp lớp hợp lệ nào. github.com/Storyyeller/Krakatau . Tôi nghĩ sẽ chính xác hơn nếu nói rằng Microsoft cung cấp một trình hợp dịch tiêu chuẩn trong khi những người viết mã Java phải tự tạo ra.
Antimony

22

Về cơ bản họ đang làm điều tương tự, MSIL là phiên bản Java bytecode của Microsoft.

Sự khác biệt chính trong nội bộ là:

  1. Bytecode được phát triển cho cả biên dịch và giải thích, trong khi MSIL được phát triển rõ ràng cho biên dịch JIT
  2. MSIL được phát triển để hỗ trợ nhiều ngôn ngữ (C # và VB.NET, v.v.) so với Bytecode chỉ được viết cho Java, dẫn đến Bytecode giống với Java hơn về mặt cú pháp so với IL dành cho bất kỳ ngôn ngữ .NET cụ thể nào.
  3. MSIL có sự phân định rõ ràng hơn giữa các loại giá trị và tham chiếu

Có thể tìm thấy nhiều thông tin hơn và so sánh chi tiết trong bài viết này của K John Gough (tài liệu tái bút)


"1.Bytecode được phát triển cho cả biên dịch và thông dịch, trong khi MSIL được phát triển rõ ràng để biên dịch JIT" - Điều này nói về cách mã Java được biên dịch thành bytecode VÀ bytecode đó được thông dịch. Tôi có đúng không? MSIL không được thông dịch để thực thi?
Abdul

2

CIL hay còn gọi là MSIL được thiết kế để con người có thể đọc được. Java bytecode thì không.

Hãy nghĩ về Java bytecode là mã máy cho phần cứng không tồn tại (nhưng JVM mô phỏng).

CIL giống ngôn ngữ hợp ngữ hơn - một bước so với mã máy, trong khi con người vẫn có thể đọc được.


Bytecode thực sự rất dễ đọc miễn là bạn có một trình soạn thảo hex. Đó là một ngôn ngữ dựa trên ngăn xếp khá đơn giản với các phần mở rộng để biểu diễn trực tiếp các lớp và phương thức. Tôi nghĩ rằng MSIL là cấp thấp hơn (ví dụ: đăng ký)?
Daniel Spiewak

en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… Một là CIL thô . Cái còn lại là mã byte được tháo rời . Bytecode có thể dễ đọc một cách hợp lý nếu bạn tìm kiếm hex, nhưng đó không phải là mục đích thiết kế.
slim

"Disassembled" thực sự là từ sai cho nó. Có thể là "khử mã hóa". Bytecode không thể đọc được trong các tệp .class chỉ vì tính nhỏ gọn. Đối với trang người dùng của javap, không có sự tháo gỡ nào liên quan đến việc tạo ra bytecode có thể đọc được từ một lớp đã biên dịch.
Daniel Spiewak

2

Không có nhiều sự khác biệt. Cả hai đều là định dạng trung gian của mã bạn đã viết. Khi được thực thi, Máy ảo sẽ thực thi ngôn ngữ trung gian được quản lý có nghĩa là Máy ảo điều khiển các biến và lệnh gọi. Thậm chí có một ngôn ngữ mà tôi không nhớ ngay bây giờ có thể chạy trên .Net và Java theo cùng một cách.

Về cơ bản, nó chỉ là một định dạng khác cho cùng một thứ

Chỉnh sửa: Đã tìm thấy ngôn ngữ (ngoài Scala): Đó là FAN ( http://www.fandev.org/ ), trông rất thú vị, nhưng chưa có thời gian để đánh giá


Scala có thể được biên dịch để nhắm mục tiêu JVM hoặc CLR, tạo ra bytecode hoặc MSIL tương ứng.
Daniel Spiewak 18-08

Thật tốt khi biết, nhưng tôi đã tìm thấy một ngôn ngữ khác cách đây một tháng hoặc lâu hơn khi đọc DZone: Tìm thấy nó! Xem chỉnh sửa bài đăng của tôi
GHad 18/09/08

1

Đồng ý, sự khác biệt là đủ phút để ăn nhập khi mới bắt đầu. Nếu bạn muốn học .Net bắt đầu từ những điều cơ bản, tôi khuyên bạn nên xem Cơ sở hạ tầng ngôn ngữ chung và Hệ thống kiểu chung.



1

Tôi nghĩ MSIL không nên so sánh với mã bytecode của Java mà là "hướng dẫn bao gồm các mã bytecodes của Java".

Không có tên của bytecode java đã được tháo rời. "Java Bytecode" phải là một bí danh không chính thức, vì tôi không thể tìm thấy tên của nó trong tài liệu chính thức. Trình gỡ mã tệp lớp Java nói

In ra mã được tháo rời, tức là, các hướng dẫn bao gồm các mã bytecodes của Java, cho mỗi phương thức trong lớp. Những điều này được ghi lại trong Đặc tả máy ảo Java.

Cả "Hướng dẫn Java VM" và "MSIL" đều được tập hợp thành mã bytecode .NET và mã Java, mà con người không thể đọc được.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.