Я новичок в .Net и сначала пытаюсь понять основы. В чем разница между байт-кодом MSIL и Java?
Чуть более общее сравнение: stackoverflow.com/questions/682608/…
Различий не так уж и много. Оба являются промежуточными форматами написанного вами кода. При запуске виртуальные машины будут выполнять управляемый промежуточный язык, что означает, что виртуальная машина управляет переменными и вызовами. Есть даже язык, который я сейчас не помню, который может одинаково работать в .Net и Java.
По сути, это просто другой формат для того же
Обновлено: нашел язык (кроме Scala): это FAN (http://www.fandev.org/), выглядит очень интересно, но пока нет времени для оценки
Scala может быть скомпилирован для целевой JVM или CLR, генерируя байт-код или MSIL соответственно.
Приятно знать, но я нашел другой язык около месяца назад, когда читал DZone: Нашел! Смотрите редактирование моего сообщения
CIL, также известный как MSIL, предназначен для чтения человеком. Байт-код Java - нет.
Думайте о байт-коде Java как о машинном коде для оборудования, которое не существует (но которое эмулирует JVM).
CIL больше похож на язык ассемблера - в одном шаге от машинного кода, но при этом удобочитаем.
Байт-код на самом деле очень удобочитаем, если у вас есть шестнадцатеричный редактор. Это довольно простой стековый язык с расширениями для прямого представления классов и методов. Я думал, что MSIL низкоуровневый (например, регистры)?
"Разобранный" - действительно неправильное слово для этого. Возможно, «расшифровано». Байт-код не читается в файлах .class просто для компактности. Обратитесь к странице руководства javap, нет никакой разборки, связанной с созданием читаемого байт-кода из скомпилированного класса.
Согласитесь, различия достаточно малы, чтобы их усвоить новичок. Если вы хотите изучить .Net, начиная с основ, я бы рекомендовал взглянуть на Common Language Infrastructure и Common Type System.
Серж Лидин написал приличную книгу о деталях MSIL: Эксперт .NET 2.0 IL Assembler. Я также смог быстро подобрать MSIL, просмотрев простые методы с использованием .NET Reflector и Ильдазм (Учебник).
Концепции между байт-кодом MSIL и Java очень похожи.
По сути, они делают то же самое, MSIL - это версия байт-кода Java от Microsoft.
Основные внутренние отличия:
Более подробную информацию и подробное сравнение можно найти в эта статья К. Джона Гофа (постскриптум).
«1. Байт-код был разработан как для компиляции, так и для интерпретации, в то время как MSIL был разработан специально для JIT-компиляции» - здесь говорится о том, как код Java компилируется до байт-кода И этот байт-код интерпретируется. Я прав? MSIL не интерпретируется для выполнения?
Прежде всего позвольте мне сказать, что я не думаю, что тонкие различия между байт-кодом Java и MSIL - это то, что должно беспокоить начинающего разработчика .NET. Оба они служат одной и той же цели - определить абстрактную целевую машину, которая является уровнем выше физической машины, используемой в конечном итоге.
Байт-код MSIL и Java очень похож, на самом деле есть инструмент под названием Кузнечик, который переводит MSIL в байт-код Java, я был частью команды разработчиков Grasshopper, поэтому я могу поделиться своими (блеклыми) знаниями. Обратите внимание, что я перестал работать над этим, когда вышла .NET framework 2.0, поэтому некоторые из этих вещей могут больше не соответствовать действительности (в таком случае, пожалуйста, оставьте комментарий, и я исправлю его).
struct
).enums
- это не более чем оболочки для целочисленных типов, в то время как Java enums
- это в значительной степени полноценные классы (спасибо Интернет-друг за комментарии).out
и ref
.Существуют и другие языковые различия, но большинство из них не выражаются на уровне байтового кода, например, если память обслуживает внутренние классы Java, отличные от static
(которые не существуют в .NET), не являются функцией байт-кода, компилятор генерирует дополнительный аргумент конструктору внутреннего класса и передает внешний объект. То же верно и для лямбда-выражений .NET.
Что касается атрибутов - аннотации Java также могут отображаться в байт-коде, так что есть эквивалент.
@Oak: аннотации Java позволяют передавать только данные, в то время как атрибуты .NET - это полностью работающие классы, которые могут иметь логику и, что наиболее важно, реализовывать интерфейсы.
Байт-код также имеет отдельные инструкции возврата для каждого типа возвращаемого типа, не знаю, действительно ли это помогает в безопасности типов.
Тот факт, что типы значений в .NET иногда могут быть размещены в стеке, имеет тривиальное значение по сравнению с тем фактом, что они имеют семантика значений; каждое место хранения типа значения является экземпляр. Напротив, каждое место хранения в Java является либо примитивной, либо беспорядочной ссылкой на объект; других видов нет.
Интересно, как они сравнивают производительность? MSIL быстрее интерпретирует, чем байт-код, например?
Я думаю, что 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.
Я написал здесь, что намного лучше. В отличие от Jasmin, он предназначен для дизассемблирования и повторной сборки любого допустимого файла класса. github.com/Storyyeller/Krakatau. Я думаю, было бы правильнее сказать, что Microsoft предоставляет стандартный ассемблер, а программисты Java должны создавать свои собственные.
Связанный вопрос: stackoverflow.com/questions/453610/…