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?

Tout d’abord, permettez-moi de dire que je ne pense pas que les différences subtiles entre le code bytecode Java et MSIL devraient déranger un développeur .NET novice. Ils ont tous deux le même objective de définir une machine cible abstraite 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 existe un outil appelé Grasshopper qui traduit le bytecode MSIL en Java, je faisais partie de l’équipe de développement de Grasshopper afin de partager un peu de mes connaissances. S’il vous plaît noter que j’ai arrêté de travailler là-dessus quand. NET Framework 2.0 est sorti, certaines de ces choses peuvent ne plus être vraies (si oui s’il vous plaît laissez un commentaire et je corrigerai).

  • .NET permet aux types définis par l’utilisateur qui ont une sémantique de valeur comme associés à la sémantique de référence régulière ( struct ).
  • .NET prend en charge les types non signés, ce qui rend l’instruction définie 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 alors que les génériques Java utilisent uniquement un effacement de type .
  • Les atsortingbuts .NET n’ont pas d’équivalent en Java (est-ce toujours vrai?).
  • Les enums .NET ne sont guère plus que des enveloppes autour des types entiers, tandis que les enums Java sont des classes à part entière (grâce à Internet Friend pour les commentaires).
  • .NET a out parameters 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 d’octet, par exemple, si la mémoire sert Java, static classes internes non static (qui n’existent pas dans .NET) ne sont pas un bytecode, le compilateur génère un argument supplémentaire au constructeur de la classe interne et passe l’object externe. La même chose est vraie pour les expressions .NET lambda.

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

Les principales différences en interne sont les suivantes:

  1. Bytecode a été développé pour la compilation et l’interprétation, alors 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.) contre Bytecode uniquement pour Java, ce qui fait que Bytecode est plus proche de Java syntaxiquement que IL pour tout langage .NET spécifique
  3. MSIL a une délimitation plus explicite entre les types valeur et référence

Vous trouverez plus d’informations et une comparaison détaillée dans cet article de K John Gough (document postscript)

CIL (le nom propre de MSIL) et le bytecode Java sont plus identiques que différents. Il existe toutefois des différences importantes:

1) CIL a été conçu dès le début pour servir de cible pour plusieurs langues. En tant que tel, il prend en charge un système de type beaucoup plus riche, y compris les types signés et non signés, les types de valeur, les pointeurs, les propriétés, les delegates, les événements, les génériques, un système d’objects avec une seule racine, etc. CIL prend en charge les fonctionnalités non requirejses pour les langages CLR initiaux (C # et VB.NET), telles que les fonctions globales et les optimisations d’appels de queue . En comparaison, le bytecode Java a été conçu comme une cible pour le langage Java et reflète de nombreuses contraintes rencontrées dans Java lui-même. Il serait beaucoup plus difficile d’écrire C ou Scheme en utilisant le bytecode Java.

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

3) Le bytecode Java a été conçu pour être interprété ou compilé alors que CIL a été conçu en supposant une compilation JIT uniquement. Cela dit, l’implémentation initiale de Mono utilisait un interprète au lieu d’un JIT.

4) CIL a été conçu ( et spécifié ) pour avoir un langage assembleur lisible par l’homme et accessible en écriture qui mappe directement au formulaire bytecode. Je crois que le bytecode Java était (comme son nom l’indique) censé être uniquement lisible par une machine. Bien sûr, le bytecode Java est relativement facilement décompilé en Java d’origine et, comme indiqué ci-dessous, il peut également être “démonté”.

Je dois noter que la JVM (la plupart d’entre eux) est plus optimisée que le CLR (n’importe lequel d’entre eux). Ainsi, les performances brutes peuvent être une raison de préférer le ciblage du bytecode Java. C’est un détail d’implémentation cependant.

Certains disent que le bytecode Java a été conçu pour être multi-plateforme alors que CIL a été conçu pour être Windows uniquement. Ce n’est pas le cas. Il y a quelques isms “Windows” dans le framework .NET mais il n’y en a pas dans CIL.

À titre d’exemple du point 4) ci-dessus, j’ai écrit un petit compilateur Java à CIL. Si vous alimentez ce compilateur le programme Java suivant:

 class Factorial{ public static void main(Ssortingng[] 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 va cracher 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 (ssortingng[] 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 } } 

Ceci est 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 accessible en écriture. Vous pouvez facilement créer des programmes CIL valides dans n'importe quel éditeur de texte.

Vous pouvez également comstackr le programme Java ci-dessus avec le compilateur javac , puis exécuter les fichiers de classe obtenus 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."":()V 4: return public static void main(java.lang.Ssortingng[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: new #3; //class Fac 6: dup 7: invokespecial #4; //Method Fac."":()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."":()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.

CIL aka MSIL se veut lisible par l’homme. Le bytecode Java ne l’est pas.

Pensez au bytecode Java comme étant du code machine pour le matériel qui n’existe pas (mais que les machines virtuelles Java émulent).

CIL ressemble plus à un langage d’assemblage – une étape du code machine, tout en restant lisible par l’homme.

Il n’y a pas beaucoup de différences. Les deux sont des formats intermédiaires du code que vous avez écrit. Lorsqu’elles sont exécutées, les machines virtuelles exécutent 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 en ce moment, qui peut fonctionner sur .Net et Java de la même manière.

Basicly, 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 le temps d’évaluer

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

Serge Lidin est l’auteur d’un livre sur les détails de MSIL: Expert .NET 2.0 IL Assembler . J’ai aussi pu rapidement prendre MSIL en regardant des méthodes simples utilisant .NET Reflector et Ildasm (Tutorial) .

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

Je pense que MSIL ne doit pas être comparé au bytecode Java, mais à “l’instruction qui comprend les bytecodes Java”.

Il n’y a pas de nom de bytecode Java démonté. “Java Bytecode” devrait être un alias non officiel, car je ne trouve pas son nom dans un document officiel. Le désassembleur de fichier de classe Java dit

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

Les deux instructions “Java VM” et “MSIL” sont assemblées en bytecode et en code Java .NET, qui ne sont pas lisibles par l’homme.