私は.Netを初めて使い、最初に基本を理解しようとしています。 MSILとJavaバイトコードの違いは何ですか?
まず、私は、JavaバイトコードとMSILの微妙な違いは、初心者の.NET開発者を悩ませるべきものだと思います。どちらも抽象を定義する同じ目的を果たします最終的に使用される物理マシンの上の層であるターゲットマシン。
MSILとJavaバイトコードは非常によく似ています。実際、MSILをJavaバイトコードに変換する Grasshopper というツールがあります。 Grasshopperの開発チームの一員であり、私の色褪せた知識を少し共有できるようにしています。NETFramework 2.0がリリースされたとき、私はこれについての作業をやめたため、これらのいくつかの事項が真実ではない可能性があることに注意してくださいコメントを残してください、私はそれを修正します)。
struct
)に相当する値セマンティクスを持つユーザー定義型を許可します。enums
は整数型のラッパーにすぎませんが、 Java enums
は完全に本格的なクラスです( Internet Friend のおかげです)コメント用)。out
およびref
パラメータがあります。他の言語の違いはありますが、それらのほとんどはバイトコードレベルで表現されていません。たとえば、メモリがJavaの非static
内部クラス(.NETには存在しない)がバイトコード機能ではない場合、コンパイラーは、内部クラスのコンストラクターに追加の引数を生成し、外部オブジェクトを渡します。同じことが.NETラムダ式にも当てはまります。
彼らは本質的に同じことをやっていて、MSILはMicrosoftのバージョンのJavaバイトコードです。
内部の主な違いは次のとおりです。
より多くの情報と詳細な比較は K John Goughによるこの記事 (追記ドキュメント)にあります。
[〜#〜] cil [〜#〜] (MSILの適切な名前)およびJavaバイトコードは、異なるよりも同じです。重要なものがあります。ただし、違い:
1)CILは最初から複数の言語のターゲットとして機能するように設計されました。そのため、符号付き型と符号なし型、値型、ポインタ、プロパティ、デリゲート、イベント、ジェネリック、単一ルートのオブジェクトシステムなど、より充実した型システムをサポートしています。 CILは、グローバル関数や tail-call最適化 など、初期のCLR言語(C#およびVB.NET)に不要な機能をサポートしています。比較すると、JavaバイトコードはJava言語のターゲットとして設計され、Javaにある多くの制約を反映しています。それ自体は、Javaバイトコードを使用してCまたはSchemeを記述するのがはるかに困難になります。
2)CILは、ネイティブライブラリやアンマネージコードに簡単に統合できるように設計されています
3)Javaバイトコードは、CITが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
}
}
これは、ilasm.exe
などのCILアセンブラに供給して実行可能ファイルを作成できる有効なCILプログラムです。ご覧のとおり、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つが非常に似ていることがわかります。
それほど大きな違いはありません。どちらも、作成したコードの中間形式です。実行すると、仮想マシンは管理された中間言語を実行します。つまり、仮想マシンが変数と呼び出しを制御します。 .NetとJavaで同じように実行できる、今は覚えていない言語もあります。
基本的に、それは同じものの単なる別のフォーマットです
編集:言語を見つけました(Scala以外):FAN( http://www.fandev.org/ )です。非常に興味深いようですが、まだ評価する時間はありません
CIL別名MSILは、人間が読めるようにすることを目的としています。 Javaバイトコードはそうではありません。
Javaバイトコードは、存在しない(しかしJVMがエミュレートする)ハードウェアのマシンコードであると考えてください)。
CILは、アセンブリ言語に似ています。機械コードからの1つのステップでありながら、人間が読める形式です。
同意された、違いは初心者として片付けるのに十分なほど微妙です。基本から.Netを学びたい場合は、Common Language InfrastructureとCommon Type Systemを確認することをお勧めします。
Serge Lidinは、MSILの詳細に関する適切な本を執筆しました: Expert .NET 2.0 IL Assembler 。 。NET Reflector と Ildasm(Tutorial) を使用して簡単な方法を確認することで、MSILをすばやく取得することもできました。
MSILとJavaバイトコードの間の概念は非常に似ています。
MSILはJavaバイトコードと比較すべきではないが、「Javaバイトコードを構成する命令)」と比較すべきではない。
逆アセンブルされた名前はありませんJavaバイトコード。「Java Bytecode」は、公式ドキュメントでその名前を見つけることができないため、非公式のエイリアスである必要があります。 The Java Class File Disassembler 言う
クラスの各メソッドについて、逆アセンブルされたコード、つまりJavaバイトコードを構成する命令を出力します。これらはJava仮想マシンに文書化されています仕様。
「Java VM命令」と「MSIL」の両方が.NETバイトコードとJavaコードにアセンブルされており、人間が読める形式ではありません。