Я новичок в .Net и сначала пытаюсь понять основы. В чем разница между байт-кодом MSIL и Java?
Я новичок в .Net и сначала пытаюсь понять основы. В чем разница между байт-кодом MSIL и Java?
Ответы:
Прежде всего позвольте мне сказать, что я не думаю, что тонкие различия между байт-кодом Java и MSIL - это то, что должно беспокоить начинающего разработчика .NET. Оба они служат одной и той же цели - определить абстрактную целевую машину, которая является уровнем выше физической машины, используемой в конечном итоге.
Байт-код MSIL и Java очень похож, на самом деле есть инструмент под названием Grasshopper, который переводит MSIL в байт-код Java, я был частью команды разработчиков Grasshopper, поэтому я могу поделиться своими (блеклыми) знаниями. Обратите внимание, что я перестал работать над этим, когда вышла .NET framework 2.0, поэтому некоторые из этих вещей могут больше не соответствовать действительности (если да, оставьте комментарий, и я исправлю его).
struct
).enums
- это не более чем оболочки для целых типов, в то время как Javaenums
- в значительной степени полноценные классы (спасибо Internet Friend за комментарии).out
и ref
параметры.Существуют и другие языковые различия, но большинство из них не выражаются на уровне байтового кода, например, если память обслуживает не static
внутренние классы Java (которые не существуют в .NET) не являются функцией байт-кода, компилятор генерирует дополнительный аргумент для конструктор внутреннего класса и передает внешний объект. То же верно и для лямбда-выражений .NET.
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 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
Выход не компилируется (насколько мне известно) , но если сравнить его с выходом КСС выше вы можете видеть , что два очень похожи.
По сути, они делают то же самое, MSIL - это версия байт-кода Java от Microsoft.
Основные внутренние отличия:
Намного больше информации и подробное сравнение можно найти в этой статье К. Джона Гофа (постскриптум).
CIL, также известный как MSIL, предназначен для чтения человеком. Байт-кода Java нет.
Думайте о байт-коде Java как о машинном коде для оборудования, которое не существует (но которое эмулирует JVM).
CIL больше похож на язык ассемблера - в одном шаге от машинного кода, но при этом удобочитаем.
Отличий не так уж и много. Оба являются промежуточными форматами написанного вами кода. При запуске виртуальные машины будут выполнять управляемый промежуточный язык, что означает, что виртуальная машина управляет переменными и вызовами. Есть даже язык, который я сейчас не помню, который может работать в .Net и Java одинаково.
По сути, это просто другой формат для того же
Изменить: нашел язык (кроме Scala): это FAN ( http://www.fandev.org/ ), выглядит очень интересно, но пока нет времени для оценки
Согласитесь, различия достаточно малы, чтобы их усвоить новичок. Если вы хотите изучить .Net, начиная с основ, я бы рекомендовал взглянуть на Common Language Infrastructure и Common Type System.
Серж Лидин написал достойную книгу о деталях MSIL: Expert .NET 2.0 IL Assembler . Я также смог быстро освоить MSIL, просмотрев простые методы с помощью .NET Reflector и Ildasm (Tutorial) .
Концепции между байт-кодом MSIL и Java очень похожи.
Я думаю, что MSIL следует сравнивать не с байт-кодом Java, а с «инструкцией, составляющей байт-коды Java».
Нет названия дизассемблированного байт-кода java. "Java Bytecode" должен быть неофициальным псевдонимом, поскольку я не могу найти его название в официальном документе. Дизассемблер файлов классов Java говорит
Распечатывает дизассемблированный код, т. Е. Инструкции, составляющие байт-коды Java, для каждого из методов класса. Они задокументированы в Спецификации виртуальной машины Java.
И «инструкции Java VM», и «MSIL» собраны в байт-код .NET и Java-код, которые не читаются человеком.