Різниця між байт-кодом MSIL та Java?


82

Я новачок у .Net і намагаюся спочатку зрозуміти основи. У чому різниця між MSIL і байт-кодом Java?


Пов’язане запитання: stackoverflow.com/questions/453610/…
Frank V

2
Трохи більш загальне порівняння за адресою: stackoverflow.com/questions/682608/…
AR

Відповіді:


75

Перш за все дозвольте мені сказати, що я не думаю, що тонкі відмінності між байт-кодом Java і MSIL - це щось, що повинно турбувати початківця розробника .NET. Вони обидва служать одній і тій же меті для визначення абстрактної цільової машини, яка є шаром над фізичною машиною, яка використовується в кінці.

Байт-код MSIL та Java дуже схожі, насправді існує інструмент під назвою Grasshopper, який перекладає MSIL на байт-код Java. Я був частиною команди розробників Grasshopper, щоб я міг поділитися частиною своїх (вицвілих) знань. Зверніть увагу, що я перестав працювати над цим, коли вийшов .NET framework 2.0, тому деякі з цих речей можуть більше не відповідати дійсності (якщо це так, будь ласка, залиште коментар, і я виправлю це).

  • .NET дозволяє визначені користувачем типи, що мають значення семантики, на відміну від звичайної посилальної семантики ( struct).
  • .NET підтримує непідписані типи, це робить набір інструкцій дещо багатшим.
  • Java включає специфікацію винятків методів у байт-коді. Хоча специфікація винятків зазвичай застосовується лише компілятором, вона може бути застосована JVM, якщо використовується завантажувач класу, відмінний від типового.
  • Загальні відомості .NET виражаються в IL, тоді як загальні засоби Java використовують лише стирання типів .
  • Атрибути .NET не мають еквівалента в Java (це все ще правда?).
  • .NET - enumsце не набагато більше, ніж обгортки навколо цілочисельних типів, тоді як Java -enums це майже повноцінні класи (спасибі Інтернет-друзям за коментарі).
  • .NET має outі refпараметри.

Існують інші мовні відмінності, але більшість з них не виражаються на рівні байтового коду, наприклад, якщо пам'ять обслуговує невнутрішні staticкласи Java (які не існують у .NET), не є функцією байт-коду, компілятор генерує додатковий аргумент для конструктор внутрішнього класу та передає зовнішній об’єкт. Те саме стосується лямбда-виразів .NET.


Щодо атрибутів - анотації Java також можна встановити для відображення в байт-коді, тому існує еквівалент.
Дуб

@Oak: Анотації Java дозволяють передавати лише дані, тоді як атрибути .NET - це повноцінні класи, які можуть мати логіку та, що найголовніше, реалізувати інтерфейси.
Федір Сойкін

Байт-код також має окремі інструкції щодо повернення для кожного типу повернення, невідомо, якщо це насправді сприяє безпеці типу.
Посудомийна машина Сесіль

1
Той факт, що типи значень у .NET іноді можуть виділятися в стеці, має тривіальне значення порівняно з тим, що вони мають семантику значень ; кожне місце зберігання типу значення є екземпляром. На відміну від цього, кожне місце зберігання в Java є або примітивним, або змішаним посиланням на об'єкт; інших типів не існує.
supercat

1
Замислювався, як вони порівнюють ефективність? Чи швидше MSIL інтерпретує байт-код, наприклад?
Люк Т О'Брайен,

23

CIL (власне ім'я для MSIL) і байт-код Java більш однакові, ніж різні. Однак є кілька важливих відмінностей:

1) CIL був розроблений з самого початку, щоб служити ціллю для багатьох мов. Таким чином, він підтримує набагато багатшу систему типів, що включає підписані та непідписані типи, типи значень, покажчики, властивості, делегати, події, узагальнюючі засоби, об'єктну систему з одним коренем тощо. CIL підтримує функції, не потрібні для початкових мов CLR (C # та VB.NET), такі як глобальні функції та оптимізація зворотних викликів . Для порівняння, байт-код Java був розроблений як цільовий для мови Java і відображає багато обмежень, виявлених у самій Java. Набагато складніше було б написати C або схему, використовуючи байт-код Java.

2) CIL був розроблений для легкої інтеграції у власні бібліотеки та некерований код

3) Байт-код Java був розроблений для інтерпретації або компіляції, тоді як CIL був розроблений, передбачаючи лише компіляцію JIT. Тим не менш, початкова реалізація Mono використовувала інтерпретатор замість JIT.

4) CIL був розроблений ( і вказаний ), щоб мати зручну для читання та записувану форму мови збірки, яка безпосередньо відображається у формі байт-коду. Я вважаю, що байт-код Java (як випливає з назви) мав бути призначений лише для машинного зчитування. Звичайно, байт-код Java порівняно легко декомпілюється до початкової Java, і, як показано нижче, його також можна "розібрати".

Слід зазначити, що JVM (більшість з них) є більш оптимізованою, ніж CLR (будь-яка з них). Отже, необроблена продуктивність може бути причиною віддавати перевагу націлюванню на байт-код Java. Однак це деталь реалізації.

Деякі люди кажуть, що байт-код Java був розроблений для мультиплатформності, тоді як CIL був розроблений лише для Windows. Це не так. У фреймворку .NET є кілька ісм "Windows", але в CIL таких немає.

Як приклад пункту 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 ;
    }
}

мій компілятор виплюне наступний 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 у будь-якому текстовому редакторі.

Ви також можете скомпілювати вищезгадану програму Java разом із javacкомпілятором, а потім запустити отримані файли класів за допомогою 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Виходу не компілюється (наскільки мені відомо) , але якщо порівняти його з виходом КСС вище ви можете бачити , що два дуже схожі.


2
Виявляється, були спроби створити зручну для читання / записувану мову збірки Java. Два, які я знайшов, - це Jasmin та Java Bytecode Assembler
Джастін,

2
Я написав тут один, який набагато кращий. На відміну від Jasmin, він розроблений, щоб мати можливість розбирати та збирати будь-який дійсний файл класу. github.com/Storyyeller/Krakatau . Думаю, було б точніше сказати, що Microsoft пропонує стандартний асемблер, тоді як кодери Java повинні робити свої власні.
Сурма

22

Вони, по суті, роблять те саме, MSIL - це версія байт-коду Java від Microsoft.

Основними відмінностями внутрішньо є:

  1. Байт-код був розроблений як для компіляції, так і для інтерпретації, тоді як MSIL був розроблений явно для компіляції JIT
  2. MSIL був розроблений для підтримки декількох мов (C # та VB.NET та ін.) Проти байт-коду, написаного лише для Java, в результаті чого байт-код синтаксично більше схожий на Java, ніж IL на будь-яку конкретну мову .NET
  3. MSIL має більш чітке розмежування між значеннями та посилальними типами

Набагато більше інформації та детальне порівняння можна знайти в цій статті К. Джона Гофа (документ приписки)


"1.Bytecode був розроблений як для компіляції, так і для інтерпретації, тоді як MSIL був розроблений явно для компіляції JIT" - Це говорить про те, як код Java компілюється до байт-коду І що байт-код інтерпретується. Я прав? Чи не виконується інтерпретація MSIL для виконання?
Абдул

2

CIL, також відомий як MSIL, призначений для читання людиною. Байт-код Java не є.

Подумайте про байт-код Java як про машинний код для обладнання, яке не існує (але яке емулюють JVM).

CIL більше схожий на асемблерну мову - на крок від машинного коду, хоча і читається людиною.


Байт-код насправді дуже читабельний, якщо у вас є шістнадцятковий редактор. Це досить проста мова на основі стека з розширеннями для безпосереднього представлення класів та методів. Я думав, що MSIL був нижчим рівнем (наприклад, реєстри)?
Даніель Співак

en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… Одним із них є необроблений CIL. Інший - розібраний байт-код. Байт-код може бути зрозумілим для читання, якщо ви переглядаєте шістнадцятковий код, але це не мета дизайну.
тонкий

"Розібраний" - це дійсно неправильне слово для цього. Можливо, "розкодовано". Байт-код не читається у файлах .class лише для компактності. На відміну від man-сторінки Javapa, ніяких розбірок, пов'язаних із створенням читаного байт-коду зі скомпільованого класу, немає.
Даніель Співак

2

Існує не так багато відмінностей. Обидва вони є проміжними форматами написаного вами коду. Після запуску віртуальні машини виконують керовану проміжну мову, що означає, що віртуальна машина контролює змінні та виклики. Існує навіть мова, яку я зараз не пам’ятаю, яка може працювати в .Net та Java однаково.

По суті, це просто інший формат того самого

Редагувати: Знайшов мову (крім Scala): Це FAN ( http://www.fandev.org/ ), виглядає дуже цікаво, але ще немає часу для оцінки


Scala може бути скомпільована для націлювання на JVM або CLR, генеруючи байт-код або MSIL відповідно.
Даніель Співак

Приємно знати, але я знайшов іншу мову місяць тому чи близько, коли читав DZone: Знайшов! Дивіться
редакцію

1

Погоджено, що різниці є достатньо мінімальними, щоб підписати новачка. Якщо ви хочете навчитися .Net, починаючи з основ, я б рекомендував ознайомитися з Інфраструктурою загальної мови та Загальною системою типів.



1

Я думаю, що MSIL не повинен порівнювати з байт-кодом Java, а "інструкцією, яка містить байт-коди Java".

Немає назви розібраного байт-коду Java. "Java Bytecode" має бути неофіційним псевдонімом, оскільки я не можу знайти його назву в офіційному документі. Java Class File Disassembler скажімо

Роздруковує розібраний код, тобто інструкції, що містять байт-коди Java, для кожного з методів у класі. Вони задокументовані у Специфікації віртуальної машини Java.

І "інструкції Java VM", і "MSIL" зібрані в байт-код .NET та код Java, які неможливо прочитати людиною.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.