Различия между байт-кодом MSIL и Java?

Я новичок в .Net и сначала пытаюсь понять основы. В чем разница между байт-кодом MSIL и Java?

Связанный вопрос: stackoverflow.com/questions/453610/…

Frank V 17.01.2009 20:09

Чуть более общее сравнение: stackoverflow.com/questions/682608/…

A R 16.06.2012 05:10
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
82
2
23 614
8

Ответы 8

Различий не так уж и много. Оба являются промежуточными форматами написанного вами кода. При запуске виртуальные машины будут выполнять управляемый промежуточный язык, что означает, что виртуальная машина управляет переменными и вызовами. Есть даже язык, который я сейчас не помню, который может одинаково работать в .Net и Java.

По сути, это просто другой формат для того же

Обновлено: нашел язык (кроме Scala): это FAN (http://www.fandev.org/), выглядит очень интересно, но пока нет времени для оценки

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

Daniel Spiewak 18.09.2008 22:20

Приятно знать, но я нашел другой язык около месяца назад, когда читал DZone: Нашел! Смотрите редактирование моего сообщения

GHad 18.09.2008 22:31

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

Думайте о байт-коде Java как о машинном коде для оборудования, которое не существует (но которое эмулирует JVM).

CIL больше похож на язык ассемблера - в одном шаге от машинного кода, но при этом удобочитаем.

Байт-код на самом деле очень удобочитаем, если у вас есть шестнадцатеричный редактор. Это довольно простой стековый язык с расширениями для прямого представления классов и методов. Я думал, что MSIL низкоуровневый (например, регистры)?

Daniel Spiewak 18.09.2008 22:19
en.wikibooks.org/wiki/…en.wikibooks.org/wiki/… One is the сырой CIL. The other is разобранный byte code. Bytecode may be reasonably readable if you grok hex, but that's not a design aim.
slim 18.09.2008 22:25

"Разобранный" - действительно неправильное слово для этого. Возможно, «расшифровано». Байт-код не читается в файлах .class просто для компактности. Обратитесь к странице руководства javap, нет никакой разборки, связанной с созданием читаемого байт-кода из скомпилированного класса.

Daniel Spiewak 18.09.2008 22:32

Согласитесь, различия достаточно малы, чтобы их усвоить новичок. Если вы хотите изучить .Net, начиная с основ, я бы рекомендовал взглянуть на Common Language Infrastructure и Common Type System.

Серж Лидин написал приличную книгу о деталях MSIL: Эксперт .NET 2.0 IL Assembler. Я также смог быстро подобрать MSIL, просмотрев простые методы с использованием .NET Reflector и Ильдазм (Учебник).

Концепции между байт-кодом MSIL и Java очень похожи.

По сути, они делают то же самое, MSIL - это версия байт-кода Java от Microsoft.

Основные внутренние отличия:

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

Более подробную информацию и подробное сравнение можно найти в эта статья К. Джона Гофа (постскриптум).

«1. Байт-код был разработан как для компиляции, так и для интерпретации, в то время как MSIL был разработан специально для JIT-компиляции» - здесь говорится о том, как код Java компилируется до байт-кода И этот байт-код интерпретируется. Я прав? MSIL не интерпретируется для выполнения?

Abdul 16.08.2016 21:54

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

Байт-код MSIL и Java очень похож, на самом деле есть инструмент под названием Кузнечик, который переводит MSIL в байт-код Java, я был частью команды разработчиков Grasshopper, поэтому я могу поделиться своими (блеклыми) знаниями. Обратите внимание, что я перестал работать над этим, когда вышла .NET framework 2.0, поэтому некоторые из этих вещей могут больше не соответствовать действительности (в таком случае, пожалуйста, оставьте комментарий, и я исправлю его).

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

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

Что касается атрибутов - аннотации Java также могут отображаться в байт-коде, так что есть эквивалент.

Oak 31.05.2010 17:56

@Oak: аннотации Java позволяют передавать только данные, в то время как атрибуты .NET - это полностью работающие классы, которые могут иметь логику и, что наиболее важно, реализовывать интерфейсы.

Fyodor Soikin 28.08.2011 05:57

Байт-код также имеет отдельные инструкции возврата для каждого типа возвращаемого типа, не знаю, действительно ли это помогает в безопасности типов.

Cecil Dishwasher 10.05.2013 22:55

Тот факт, что типы значений в .NET иногда могут быть размещены в стеке, имеет тривиальное значение по сравнению с тем фактом, что они имеют семантика значений; каждое место хранения типа значения является экземпляр. Напротив, каждое место хранения в Java является либо примитивной, либо беспорядочной ссылкой на объект; других видов нет.

supercat 24.07.2013 03:40

Интересно, как они сравнивают производительность? MSIL быстрее интерпретирует, чем байт-код, например?

Luke T O'Brien 13.10.2017 17:26

Я думаю, что MSIL следует сравнивать не с байт-кодом Java, а с «инструкцией, составляющей байт-коды Java».

Нет названия дизассемблированного байт-кода Java. «Байт-код Java» должен быть неофициальным псевдонимом, поскольку я не могу найти его название в официальном документе. Дизассемблер файлов классов 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-инструкции VM", и "MSIL" собраны в байт-код .NET и Java-код, которые не читаются человеком.

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

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

2) CIL был разработан для простой интеграции в собственные библиотеки и неуправляемый код.

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

4) CIL был разработан (и указал), чтобы иметь удобочитаемую и доступную для записи форму языка ассемблера, которая отображается непосредственно на форму байт-кода. Я считаю, что байт-код Java (как следует из названия) предназначался только для машинного чтения. Конечно, байт-код Java относительно легко декомпилируется обратно в исходную Java, и, как показано ниже, его также можно «разобрать».

Я должен отметить, что JVM (большинство из них) более оптимизировано, чем CLR (любая из них). Таким образом, чистая производительность может быть причиной предпочесть таргетинг на байт-код Java. Однако это деталь реализации.

Некоторые люди говорят, что байт-код Java был разработан как многоплатформенный, в то время как CIL был разработан только для Windows. Это не тот случай. В .NET framework есть некоторые "измы" 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 не компилируется (насколько мне известно), но если вы сравните его с выводом CIL выше, вы увидите, что они очень похожи.

Оказывается, были попытки создать читаемый / записываемый язык ассемблера Java. Два, которые я нашел, - это Жасмин и Ассемблер байт-кода Java.

Justin 20.02.2012 22:56

Я написал здесь, что намного лучше. В отличие от Jasmin, он предназначен для дизассемблирования и повторной сборки любого допустимого файла класса. github.com/Storyyeller/Krakatau. Я думаю, было бы правильнее сказать, что Microsoft предоставляет стандартный ассемблер, а программисты Java должны создавать свои собственные.

Antimony 08.05.2013 21:43

Другие вопросы по теме