Я новачок у .Net і намагаюся спочатку зрозуміти основи. У чому різниця між MSIL і байт-кодом Java?
Я новачок у .Net і намагаюся спочатку зрозуміти основи. У чому різниця між MSIL і байт-кодом Java?
Відповіді:
Перш за все дозвольте мені сказати, що я не думаю, що тонкі відмінності між байт-кодом Java і MSIL - це щось, що повинно турбувати початківця розробника .NET. Вони обидва служать одній і тій же меті для визначення абстрактної цільової машини, яка є шаром над фізичною машиною, яка використовується в кінці.
Байт-код MSIL та Java дуже схожі, насправді існує інструмент під назвою Grasshopper, який перекладає MSIL на байт-код Java. Я був частиною команди розробників Grasshopper, щоб я міг поділитися частиною своїх (вицвілих) знань. Зверніть увагу, що я перестав працювати над цим, коли вийшов .NET framework 2.0, тому деякі з цих речей можуть більше не відповідати дійсності (якщо це так, будь ласка, залиште коментар, і я виправлю це).
struct
).enums
це не набагато більше, ніж обгортки навколо цілочисельних типів, тоді як Java -enums
це майже повноцінні класи (спасибі Інтернет-друзям за коментарі).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 є кілька ісм "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, починаючи з основ, я б рекомендував ознайомитися з Інфраструктурою загальної мови та Загальною системою типів.
Серж Лідін написав пристойну книгу про деталі MSIL: Expert .NET 2.0 IL Assembler . Я також зміг швидко підібрати MSIL, переглянувши прості методи, використовуючи .NET Reflector та Ildasm (Підручник) .
Поняття між байткодом MSIL та Java дуже схожі.
Я думаю, що MSIL не повинен порівнювати з байт-кодом Java, а "інструкцією, яка містить байт-коди Java".
Немає назви розібраного байт-коду Java. "Java Bytecode" має бути неофіційним псевдонімом, оскільки я не можу знайти його назву в офіційному документі. Java Class File Disassembler скажімо
Роздруковує розібраний код, тобто інструкції, що містять байт-коди Java, для кожного з методів у класі. Вони задокументовані у Специфікації віртуальної машини Java.
І "інструкції Java VM", і "MSIL" зібрані в байт-код .NET та код Java, які неможливо прочитати людиною.