web-dev-qa-db-ja.com

MSILとJavaバイトコード?

私は.Netを初めて使い、最初に基本を理解しようとしています。 MSILとJavaバイトコードの違いは何ですか?

78
user18055

まず、私は、JavaバイトコードとMSILの微妙な違いは、初心者の.NET開発者を悩ませるべきものだと思います。どちらも抽象を定義する同じ目的を果たします最終的に使用される物理マシンの上の層であるターゲットマシン。

MSILとJavaバイトコードは非常によく似ています。実際、MSILをJavaバイトコードに変換する Grasshopper というツールがあります。 Grasshopperの開発チームの一員であり、私の色褪せた知識を少し共有できるようにしています。NETFramework 2.0がリリースされたとき、私はこれについての作業をやめたため、これらのいくつかの事項が真実ではない可能性があることに注意してくださいコメントを残してください、私はそれを修正します)。

  • .NETは、regular参照セマンティクス(struct)に相当する値セマンティクスを持つユーザー定義型を許可します。
  • .NETは符号なしの型をサポートします。これにより、命令セットが少しリッチになります。
  • Javaでは、バイトコードにメソッドの例外仕様が含まれています。通常、例外の指定はコンパイラーによってのみ実施されますが、デフォルト以外のクラスローダーが使用されている場合は、JVMによって実施される場合があります。
  • .NETジェネリックはILで表現されますが、Javaジェネリックは type erasure のみを使用します)。
  • .NET属性には、Java(これはまだ正しいですか?).
  • .NET enumsは整数型のラッパーにすぎませんが、 Java enums は完全に本格的なクラスです( Internet Friend のおかげです)コメント用)。
  • .NETにはoutおよびrefパラメータがあります。

他の言語の違いはありますが、それらのほとんどはバイトコードレベルで表現されていません。たとえば、メモリがJavaの非static内部クラス(.NETには存在しない)がバイトコード機能ではない場合、コンパイラーは、内部クラスのコンストラクターに追加の引数を生成し、外部オブジェクトを渡します。同じことが.NETラムダ式にも当てはまります。

73
Motti

彼らは本質的に同じことをやっていて、MSILはMicrosoftのバージョンのJavaバイトコードです。

内部の主な違いは次のとおりです。

  1. バイトコードはコンパイルと解釈の両方のために開発されましたが、MSILはJITコンパイルのために明示的に開発されました
  2. MSILは複数の言語(C#やVB.NETなど)をサポートするために開発されたもので、バイトコードはJava専用に記述されているため、バイトコードはJavaに似ています) NET言語
  3. MSILには、値と参照型の間のより明確な境界があります

より多くの情報と詳細な比較は K John Goughによるこの記事 (追記ドキュメント)にあります。

22
Guy Starbuck

[〜#〜] 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つが非常に似ていることがわかります。

20
Justin

それほど大きな違いはありません。どちらも、作成したコードの中間形式です。実行すると、仮想マシンは管理された中間言語を実行します。つまり、仮想マシンが変数と呼び出しを制御します。 .NetとJavaで同じように実行できる、今は覚えていない言語もあります。

基本的に、それは同じものの単なる別のフォーマットです

編集:言語を見つけました(Scala以外):FAN( http://www.fandev.org/ )です。非常に興味深いようですが、まだ評価する時間はありません

2
GHad

CIL別名MSILは、人間が読めるようにすることを目的としています。 Javaバイトコードはそうではありません。

Javaバイトコードは、存在しない(しかしJVMがエミュレートする)ハードウェアのマシンコードであると考えてください)。

CILは、アセンブリ言語に似ています。機械コードからの1つのステップでありながら、人間が読める形式です。

2
slim

同意された、違いは初心者として片付けるのに十分なほど微妙です。基本から.Netを学びたい場合は、Common Language InfrastructureとCommon Type Systemを確認することをお勧めします。

1
Internet Friend

Serge Lidinは、MSILの詳細に関する適切な本を執筆しました: Expert .NET 2.0 IL Assembler。NET ReflectorIldasm(Tutorial) を使用して簡単な方法を確認することで、MSILをすばやく取得することもできました。

MSILとJavaバイトコードの間の概念は非常に似ています。

1
Jeffrey LeCours

MSILはJavaバイトコードと比較すべきではないが、「Javaバイトコードを構成する命令)」と比較すべきではない。

逆アセンブルされた名前はありませんJavaバイトコード。「Java Bytecode」は、公式ドキュメントでその名前を見つけることができないため、非公式のエイリアスである必要があります。 The Java Class File Disassembler 言う

クラスの各メソッドについて、逆アセンブルされたコード、つまりJavaバイトコードを構成する命令を出力します。これらはJava仮想マシンに文書化されています仕様。

「Java VM命令」と「MSIL」の両方が.NETバイトコードとJavaコードにアセンブルされており、人間が読める形式ではありません。

1
Dennis C