web-dev-qa-db-fra.com

Différences entre MSIL et Java bytecode?

Je suis nouveau sur .Net et j'essaie d'abord de comprendre les bases. Quelle est la différence entre MSIL et Java bytecode?

78
user18055

Tout d'abord, permettez-moi de dire que je ne pense pas que les différences subtiles entre Java bytecode et MSIL soient quelque chose qui devrait déranger un développeur .NET novice. Ils ont tous deux le même objectif de définir un résumé machine cible qui est une couche au-dessus de la machine physique utilisée à la fin.

MSIL et Java bytecode sont très similaires, en fait il y a un outil appelé Grasshopper qui traduit MSIL en Java bytecode, j'étais faisant partie de l'équipe de développement de Grasshopper afin que je puisse partager un peu de mes connaissances (fanées). Veuillez noter que j'ai cessé de travailler sur ce sujet lorsque .NET Framework 2.0 est sorti, donc certaines de ces choses peuvent ne plus être vraies (si c'est le cas) veuillez laisser un commentaire et je le corrigerai).

  • .NET autorise les types définis par l'utilisateur qui ont une sémantique de valeur par rapport à la sémantique de référence régulière (struct).
  • .NET prend en charge les types non signés, ce qui rend le jeu d'instructions un peu plus riche.
  • Java inclut la spécification d'exception des méthodes dans le bytecode. Bien que la spécification d'exception ne soit généralement appliquée que par le compilateur, elle peut être appliquée par la JVM si un chargeur de classe autre que celui par défaut est utilisé.
  • Les génériques .NET sont exprimés en IL tandis que Java n'utilisent que effacement de type .
  • Les attributs .NET n'ont pas d'équivalent dans Java (est-ce toujours vrai?).
  • .NET enums ne sont pas beaucoup plus que des wrappers autour de types entiers alors que Java enums sont des classes à part entière (grâce à Internet Friend pour commenter).
  • .NET a les paramètres out et ref.

Il existe d'autres différences de langage, mais la plupart d'entre elles ne sont pas exprimées au niveau du code octet, par exemple si la mémoire sert aux classes internes nonstatic de Java (qui n'existent pas dans .NET) ne sont pas une fonctionnalité de bytecode, le Le compilateur génère un argument supplémentaire au constructeur de la classe interne et transmet l'objet externe. Il en va de même pour les expressions lambda .NET.

73
Motti

Ils font essentiellement la même chose, MSIL est la version Microsoft de Java bytecode.

Les principales différences internes sont:

  1. Bytecode a été développé pour la compilation et l'interprétation, tandis que MSIL a été développé explicitement pour la compilation JIT
  2. MSIL a été développé pour prendre en charge plusieurs langages (C # et VB.NET, etc.) par rapport au Bytecode écrit uniquement pour Java, ce qui fait que le Bytecode est plus similaire à Java syntaxiquement qu'IL à tout autre). Langue NET
  3. MSIL a une délimitation plus explicite entre les types valeur et référence

Beaucoup plus d'informations et une comparaison détaillée peuvent être trouvées dans cet article de K John Gough (document postscript)

22
Guy Starbuck

CIL (le nom propre pour MSIL) et Java bytecode sont plus les mêmes que les différents. Il y a quelques importants différences cependant:

1) CIL a été conçu dès le départ pour servir de cible pour plusieurs langues. En tant que tel, il prend en charge un système de types beaucoup plus riche comprenant des types signés et non signés, des types de valeur, des pointeurs, des propriétés, des délégués, des événements, des génériques, un système d'objets avec une seule racine, et plus encore. CIL prend en charge les fonctionnalités non requises pour les langages CLR initiaux (C # et VB.NET) telles que les fonctions globales et optimisations des appels de queue . En comparaison, Java bytecode a été conçu comme une cible pour le langage Java et reflète de nombreuses contraintes trouvées dans Java Il serait beaucoup plus difficile d’écrire C ou Scheme en utilisant Java bytecode.

2) CIL a été conçu pour s'intégrer facilement dans les bibliothèques natives et le code non managé

3) Java bytecode a été conçu pour être interprété ou compilé alors que CIL a été conçu en supposant la compilation JIT uniquement. Cela dit, l'implémentation initiale de Mono a utilisé un interpréteur au lieu de un JIT.

4) CIL a été conçu ( et spécifié ) pour avoir une forme de langage d'assemblage lisible et inscriptible par l'homme qui correspond directement à la forme de bytecode. Je crois que Java bytecode était (comme son nom l'indique) destiné à être uniquement lisible par machine. Bien sûr, Java bytecode est relativement facilement décompilé de nouveau à l'original) Java et, comme indiqué ci-dessous, il peut également être "démonté".

Je dois noter que la JVM (la plupart d'entre eux) est plus hautement optimisée que la CLR (aucune d'entre elles). Ainsi, les performances brutes pourraient être une raison de préférer le ciblage Java bytecode. C'est un détail d'implémentation cependant.

Certaines personnes disent que le Java bytecode a été conçu pour être multi-plateforme alors que CIL a été conçu pour être uniquement Windows. Ce n'est pas le cas. Il y a quelques ismes "Windows" dans le framework .NET mais il n'y en a pas dans CIL.

Comme exemple du point numéro 4) ci-dessus, j'ai écrit un jouet Java au compilateur CIL il y a quelque temps. Si vous alimentez ce compilateur, le programme Java 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 ;
    }
}

mon compilateur crachera le CIL suivant:

.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
   }
}

Il s'agit d'un programme CIL valide qui peut être introduit dans un assembleur CIL comme ilasm.exe pour créer un exécutable. Comme vous pouvez le voir, CIL est un langage entièrement lisible et inscriptible par l'homme. Vous pouvez facilement créer des programmes CIL valides dans n'importe quel éditeur de texte.

Vous pouvez également compiler le programme Java ci-dessus avec le compilateur javac, puis exécuter les fichiers de classe résultants via le "désassembleur" javap pour obtenir les éléments suivants:

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
}

La sortie javap n'est pas compilable (à ma connaissance) mais si vous la comparez à la sortie CIL ci-dessus, vous pouvez voir que les deux sont très similaires.

20
Justin

Il n'y a pas tant de différences. Les deux sont des formats intermédiaires du code que vous avez écrit. Une fois exécutées, les machines virtuelles exécuteront le langage intermédiaire géré, ce qui signifie que la machine virtuelle contrôle les variables et les appels. Il y a même un langage que je ne me souviens pas actuellement qui peut fonctionner sur .Net et Java de la même manière.

Fondamentalement, c'est juste un autre format pour la même chose

Edit: Trouvé la langue (en plus de Scala): C'est FAN ( http://www.fandev.org/ ), semble très intéressant, mais pas encore le temps d'évaluer

2
GHad

CIL aka MSIL est conçu pour être lisible par l'homme. Java bytecode ne l'est pas.

Considérez Java bytecode comme étant le code machine d'un matériel qui n'existe pas (mais que les JVM émulent).

CIL ressemble plus au langage d'assemblage - une étape du code machine, tout en étant lisible par l'homme.

2
slim

D'accord, les différences sont suffisamment infimes pour devenir un débutant. Si vous voulez apprendre .Net à partir des bases, je vous recommande de regarder l'infrastructure de langage commun et le système de type commun.

1
Internet Friend

Serge Lidin a écrit un livre décent sur les détails de MSIL: Expert .NET 2.0 IL Assembler . J'ai également pu rapidement prendre MSIL en regardant des méthodes simples en utilisant . NET Reflector et Ildasm (Tutorial) .

Les concepts entre MSIL et Java bytecode sont très similaires.

1
Jeffrey LeCours

Je pense que MSIL ne devrait pas se comparer à Java bytecode, mais "l'instruction qui comprend les Java bytecodes").

Il n'y a pas de nom de Java bytecode. "Java Bytecode" devrait être un alias non officiel, car je ne trouve pas son nom dans le document officiel. Le Java Class File Disassembler say

Imprime le code désassemblé, c'est-à-dire les instructions qui composent les Java bytecodes, pour chacune des méthodes de la classe. Celles-ci sont documentées dans la machine virtuelle Java Spécification.

Les deux "Java VM" et "MSIL" sont assemblés en bytecode .NET et Java, qui ne sont pas lisibles par l'homme).

1
Dennis C