Прежде всего позвольте мне сказать, что я не думаю, что тонкие различия между байт-кодом 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- это не более чем оболочки для целых типов, в то время как Javaenums - в значительной степени полноценные классы (спасибо Internet Friend за комментарии).
.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 framework есть некоторые "измы" Windows, но их нет в CIL.
В качестве примера пункта 4 выше я написал игрушечный компилятор Java для CIL некоторое время назад. Если вы скармливаете этому компилятору следующую программу Java:
.assembly extern mscorlib { }
.assembly 'Factorial' { .ver 0:0:0:0 }
.class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object
{
.method publicstaticdefaultvoidmain(string[] a) cil managed
{
.entrypoint
.maxstack 16
newobj instance voidclassFac::'.ctor'()
ldc.i4 3
callvirtinstanceint32classFac::ComputeFac (int32)
callvoidclass [mscorlib]System.Console::WriteLine(int32)
ret
}
}
.classprivateFacextends [mscorlib]System.Object{
.method public instance defaultvoid'.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«дизассемблер», чтобы получить следующее:
Оказывается, были попытки создать читаемый / записываемый язык ассемблера Java. Два, которые я нашел, - это Jasmin и Java Bytecode Assembler
Джастин
2
Я написал здесь, что намного лучше. В отличие от Jasmin, он разработан, чтобы иметь возможность дизассемблировать и повторно собирать любой допустимый файл класса. github.com/Storyyeller/Krakatau . Я думаю, было бы правильнее сказать, что Microsoft предоставляет стандартный ассемблер, в то время как программисты Java должны создавать свои собственные.
Сурьма
22
По сути, они делают то же самое, MSIL - это версия байт-кода Java от Microsoft.
Основные внутренние отличия:
Байт-код был разработан как для компиляции, так и для интерпретации, в то время как MSIL был разработан специально для JIT-компиляции.
MSIL был разработан для поддержки нескольких языков (C # и VB.NET и т. Д.) По сравнению с байт-кодом, написанным только для Java, в результате чего байт-код более похож на Java синтаксически, чем IL для любого конкретного языка .NET.
MSIL имеет более четкое разграничение между типами значений и ссылками.
Намного больше информации и подробное сравнение можно найти в этой статье К. Джона Гофа (постскриптум).
«1. Байт-код был разработан как для компиляции, так и для интерпретации, в то время как MSIL был разработан специально для JIT-компиляции» - здесь говорится о том, как Java-код компилируется в байт-код И этот байт-код интерпретируется. Я прав? MSIL не интерпретируется для выполнения?
Абдул
2
CIL, также известный как MSIL, предназначен для чтения человеком. Байт-кода Java нет.
Думайте о байт-коде Java как о машинном коде для оборудования, которое не существует (но которое эмулирует JVM).
CIL больше похож на язык ассемблера - в одном шаге от машинного кода, но при этом удобочитаем.
Байт-код на самом деле очень удобочитаем, если у вас есть шестнадцатеричный редактор. Это довольно простой стековый язык с расширениями для прямого представления классов и методов. Я думал, что MSIL нижнего уровня (например регистры)?
Даниэль Спивак
en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… Один из них - это необработанный CIL. Другой - это дизассемблированный байт-код. Байт-код может быть достаточно читабельным, если вы попробуете шестнадцатеричный код, но это не цель дизайна.
slim
"Разобранный" - действительно неправильное слово для этого. Возможно, «расшифровано». Байт-код не читается в файлах .class просто для компактности. Обратитесь к странице руководства javap, нет никакой разборки, связанной с созданием читаемого байт-кода из скомпилированного класса.
Даниэль Спивак,
2
Отличий не так уж и много. Оба являются промежуточными форматами написанного вами кода. При запуске виртуальные машины будут выполнять управляемый промежуточный язык, что означает, что виртуальная машина управляет переменными и вызовами. Есть даже язык, который я сейчас не помню, который может работать в .Net и Java одинаково.
По сути, это просто другой формат для того же
Изменить: нашел язык (кроме Scala): это FAN ( http://www.fandev.org/ ), выглядит очень интересно, но пока нет времени для оценки
Scala может быть скомпилирован для работы с JVM или CLR, генерируя байт-код или MSIL соответственно.
Даниэль Спивак,
Приятно знать, но я нашел другой язык около месяца назад, когда читал DZone: Нашел! См. Редактирование моего сообщения
GHad
1
Согласитесь, различия достаточно малы, чтобы их усвоить новичок. Если вы хотите изучить .Net, начиная с основ, я бы рекомендовал взглянуть на Common Language Infrastructure и Common Type System.
Я думаю, что MSIL следует сравнивать не с байт-кодом Java, а с «инструкцией, составляющей байт-коды Java».
Нет названия дизассемблированного байт-кода java. "Java Bytecode" должен быть неофициальным псевдонимом, поскольку я не могу найти его название в официальном документе.
Дизассемблер файлов классов Java говорит
Распечатывает дизассемблированный код, т. Е. Инструкции, составляющие байт-коды Java, для каждого из методов класса. Они задокументированы в Спецификации виртуальной машины Java.
И «инструкции Java VM», и «MSIL» собраны в байт-код .NET и 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 VM», и «MSIL» собраны в байт-код .NET и Java-код, которые не читаются человеком.
источник