Различия между MSIL и Java байт-кодом? - PullRequest
76 голосов
/ 18 сентября 2008

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

Ответы [ 8 ]

71 голосов
/ 18 сентября 2008

Прежде всего позвольте мне сказать, что я не думаю, что тонкие различия между байт-кодом 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 в значительной степени являются полноценными классами (спасибо Internet Friend за комментирование).
  • .NET имеет параметры out и ref.

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

22 голосов
/ 18 сентября 2008

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

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

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

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

20 голосов
/ 06 февраля 2012

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

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

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

3) Байт-код Java был разработан для интерпретации или компиляции, в то время как CIL был спроектирован только с использованием JIT-компиляции. Тем не менее, первоначальная реализация Mono использовала интерпретатор вместо 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 выше, вы увидите, что они очень похожи.

2 голосов
/ 18 сентября 2008

CIL aka MSIL предназначен для чтения человеком. Java байт-код не является.

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

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

2 голосов
/ 18 сентября 2008

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

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

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

1 голос
/ 30 ноября 2008

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

Нет имени дизассемблированного байт-кода Java. «Java Bytecode» должен быть неофициальным псевдонимом, поскольку я не могу найти его название в официальном документе. дизассемблер файлов классов Java скажем

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

Обе команды Java VM и MSIL собраны в байт-код .NET и код Java, которые не читаются человеком.

1 голос
/ 18 сентября 2008

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

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

1 голос
/ 18 сентября 2008

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

...