Question

En guise de suivi à la question intitulée Différences entre le bytecode MSIL et Java? , quelles sont les différences ou similitudes (majeures) entre le fonctionnement de la machine virtuelle Java et le fonctionnement du .NET Framework Common Language Runtime (CLR)?

De plus, le .NET Framework CLR est-il une & machine virtuelle &>; ou n'a-t-il pas les attributs d'une machine virtuelle?

Était-ce utile?

La solution

Il existe de nombreuses similitudes entre les deux implémentations (et à mon avis: oui, ce sont les & "; machines virtuelles &";).

D'une part, ce sont deux machines virtuelles basées sur des piles, sans aucune notion de & "registres &"; comme nous sommes habitués à voir dans un processeur moderne comme le x86 ou PowerPC. L'évaluation de toutes les expressions ((1 + 1) / 2) est effectuée en plaçant des opérandes sur la & "Pile &"; puis en extrayant ces opérandes de la pile chaque fois qu'une instruction (addition, division, etc.) doit consommer ces opérandes. Chaque instruction place ses résultats dans la pile.

C’est un moyen pratique d’implémenter une machine virtuelle, car chaque processeur dans le monde possède une pile, mais le nombre de registres est souvent différent (et certains registres ont un but spécifique, et chaque instruction attend ses opérandes dans différents registres, etc.).

Donc, si vous envisagez de modéliser une machine abstraite, un modèle purement basé sur une pile est un très bon moyen.

Bien sûr, les vraies machines ne fonctionnent pas de cette façon. Le compilateur JIT est donc responsable de l'exécution de & Quot; enregistrement & Quot; nombre d’opérations de bytecode, consistant essentiellement à programmer les registres de la CPU pour contenir des opérandes et des résultats lorsque cela est possible.

Donc, je pense que c'est l'un des plus grands points communs entre le CLR et la JVM.

En ce qui concerne les différences ...

Une différence intéressante entre les deux implémentations est que le CLR inclut des instructions pour la création de types génériques, puis pour l’application de spécialisations paramétriques à ces types. Ainsi, à l'exécution, le CLR considère une liste & Lt; int & Gt; être d'un type complètement différent d'une liste < String >.

Sous les couvertures, il utilise le même fichier MSIL pour toutes les spécialisations de type référence (donc une liste < String > utilise la même implémentation qu'un liste < objet > ;, avec des transformations typographiques différentes aux limites de l’API), mais chaque type de valeur utilise sa propre implémentation unique (List < int > génère un code complètement différent de List < double gt;).

En Java, les types génériques sont un pur truc de compilateur. La JVM n'a aucune idée des classes qui ont des arguments de type et ne peut pas effectuer de spécialisations paramétriques à l'exécution.

D'un point de vue pratique, cela signifie que vous ne pouvez pas surcharger les méthodes Java sur des types génériques. Vous ne pouvez pas avoir deux méthodes différentes, avec le même nom, qui diffèrent uniquement par l'acceptation d'une liste & Lt; String & Gt; ou une liste & Date > ;. Bien entendu, le CLR étant au courant des types paramétriques, il n’a aucun problème à gérer les méthodes surchargées dans les spécialisations de types génériques.

Au jour le jour, c’est la différence que je remarque le plus entre le CLR et le JVM.

Les autres différences importantes incluent:

  • Le CLR a des fermetures (implémentées en tant que délégués C #). La machine virtuelle Java ne prend en charge les fermetures que depuis Java 8.

  • Le CLR a des coroutines (implémentées avec le mot-clé 'rendement' C #). La JVM ne le fait pas.

  • Le CLR permet au code utilisateur de définir de nouveaux types de valeur (structs), tandis que la machine virtuelle Java fournit un ensemble fixe de types de valeur (octet, court, int, long, float, double, char, booléen) et permet uniquement les utilisateurs à définir de nouveaux types de référence (classes).

  • Le CLR fournit un support pour la déclaration et la manipulation de pointeurs. Ceci est particulièrement intéressant car la JVM et le CLR utilisent des implémentations de collecteur de déchets générationnelles strictes comme stratégie de gestion de la mémoire. Dans des circonstances ordinaires, un CPG de compactage strict a beaucoup de difficultés avec les pointeurs, car lorsque vous déplacez une valeur d'un emplacement de mémoire à un autre, tous les pointeurs (et les pointeurs à pointeurs) deviennent invalides. Mais le CLR fournit un & Quot; épinglage & Quot; mécanisme permettant aux développeurs de déclarer un bloc de code dans lequel le CLR n'est pas autorisé à déplacer certains pointeurs. C'est très convenient.

  • La plus grande unité de code de la machine virtuelle Java est soit un "package" comme en témoigne le mot clé "protected", soit un JAR (c'est-à-dire une archive Java), comme en témoigne le fait de pouvoir spécifier un fichier jar dans le chemin de classe et faites-le traiter comme un dossier de code. Dans le CLR, les classes sont agrégées dans des "assemblys" et le CLR fournit une logique permettant de raisonner sur les assemblys et de les manipuler (chargés dans & "AppDomains &"), Fournissant des sandbox de niveau sous-application pour l'allocation de mémoire. et exécution de code).

  • Le format de bytecode CLR (composé d'instructions MSIL et de métadonnées) comporte moins de types d'instructions que la machine virtuelle Java. Dans la machine virtuelle Java, chaque opération unique (ajouter deux valeurs int, ajouter deux valeurs flottantes, etc.) a sa propre instruction unique. Dans le CLR, toutes les instructions MSIL sont polymorphes (ajoutez deux valeurs) et le compilateur JIT est chargé de déterminer les types des opérandes et de créer le code machine approprié. Je ne sais pas quelle est la stratégie de préférence, cependant. Les deux ont des compromis. Le compilateur HotSpot JIT, pour la machine virtuelle Java, peut utiliser un mécanisme de génération de code plus simple (il n'est pas nécessaire de déterminer les types d'opérandes, car ils sont déjà codés dans l'instruction), mais cela nécessite un format de code octet plus complexe. avec plus de types d'instruction.

J'utilise Java (et j'admire la JVM) depuis environ dix ans maintenant.

Mais, à mon avis, le CLR est désormais la meilleure implémentation, à presque tous les égards.

Autres conseils

Votre première question consiste à comparer la machine virtuelle avec le .NET Framework. Je suppose que vous vouliez en fait comparer avec le CLR. Si tel est le cas, je pense que vous pourriez écrire un petit livre à ce sujet ( MODIFIER: ressemble à ce que Benji a déjà :-)

Une différence importante est que le CLR est conçu pour être une architecture indépendante du langage, contrairement à la JVM.

Une autre différence importante est que le CLR a été spécialement conçu pour permettre un niveau élevé d’interopérabilité avec le code natif. Cela signifie que le CLR doit gérer la fiabilité et la sécurité lors de l'accès et de la modification de la mémoire native, ainsi que gérer le marshalling entre les structures de données CLR et les structures de données natives.

Pour répondre à votre deuxième question, utilisez le terme & # 8220; machine virtuelle & # 8221; est un terme plus ancien du monde du matériel (par exemple, la virtualisation de la 360 dans les années 60 par IBM &; 8217) qui signifiait autrefois une émulation logicielle / matérielle de la machine sous-jacente pour réaliser le même genre de choses que VMWare.

Le CLR est souvent appelé un & moteur d’exécution &. Dans ce contexte, il s’agit d’une implémentation d’une machine IL par-dessus un x86. C’est également ce que fait la machine virtuelle Java, bien que vous puissiez affirmer qu’il existe une différence importante entre les codes octets polymorphes du CLR et les codes octets typés de la machine virtuelle.

La réponse pédante à votre deuxième question est donc & "non &"; Mais il s’agit vraiment de définir ces deux termes.

EDIT: Une autre différence entre la JVM et le CLR est que la JVM (version 6) est très réticent à restituer la mémoire allouée au système d'exploitation, même s'il le peut.

Par exemple, supposons qu'un processus JVM démarre et alloue initialement 25 Mo de mémoire à partir du système d'exploitation. Le code de l'application tente ensuite des allocations nécessitant 50 Mo supplémentaires. La JVM allouera 50 Mo supplémentaires à partir du système d'exploitation. Une fois que le code de l'application a cessé d'utiliser cette mémoire, il est collecté et la taille du segment de mémoire de la JVM diminue. Toutefois, la machine virtuelle Java ne libèrera la mémoire allouée au système d'exploitation que dans certaines circonstances très spécifiques Sinon, cette mémoire restera allouée pendant le reste de la durée de vie du processus.

Le CLR, en revanche, restitue la mémoire allouée au système d’exploitation si elle n’est plus nécessaire. Dans l'exemple ci-dessus, le CLR aurait libéré la mémoire une fois que le tas aurait diminué.

Plus de détails sur les différences peuvent être trouvés chez diverses sources académiques et privées. Les Choix de conception de CLR constituent un bon exemple.

Certains exemples spécifiques incluent:

  • Certains opérateurs de bas niveau sont tapés, tels que & "ajouter deux ints &"; où en tant que CLR utilise un opérande polymorphe. (i.e. fadd / iadd / ladd vs simplement ajouter)
  • Actuellement, la machine virtuelle Java effectue une optimisation du profilage et de l'exécution au moment de l'exécution (par exemple, Hotspot). CLR effectue actuellement les optimisations JIT, mais pas l'optimisation de l'exécution (c'est-à-dire remplacer le code pendant l'exécution).
  • CLR ne met pas les méthodes virtuelles en ligne, JVM fait ...
  • Prise en charge des types de valeur dans le CLR au-delà des & primitives & ";

Le CLR et la machine virtuelle Java sont tous deux des machines virtuelles.

.NET Framework et Java Runtime Environment regroupent les ordinateurs virtuels respectifs et leurs bibliothèques. Sans bibliothèques, les machines virtuelles sont plutôt inutiles.

Ce n'est pas une machine virtuelle, le framework .net compile les assemblys en binaire natif lors de la première exécution:

En informatique, la compilation juste-à-temps (JIT), également appelée traduction dynamique, est une technique permettant d’améliorer les performances d’exécution d’un programme informatique. JIT s'appuie sur deux idées antérieures dans les environnements d'exécution: la compilation par code intermédiaire et la compilation dynamique. Il convertit le code au moment de l'exécution avant de l'exécuter en mode natif, par exemple le bytecode en code machine natif. L’amélioration des performances par rapport aux interprètes provient de la mise en cache des résultats de la traduction de blocs de code et non de la réévaluation de chaque ligne ou opérande à chaque fois qu’il est rencontré (voir Langage interprété). Il présente également des avantages par rapport à la compilation statique du code au moment du développement, car il peut recompiler le code si cela s'avère avantageux et peut également appliquer des garanties de sécurité. JIT peut ainsi combiner certains des avantages de l’interprétation et de la compilation statique (à l’avance).

Plusieurs environnements d'exécution modernes, tels que le .NET Framework de Microsoft, la plupart des implémentations de Java et plus récemment, Actionscript 3, reposent sur la compilation JIT pour l'exécution de code à haute vitesse.

Source: http://en.wikipedia.org/wiki/Just-in -time_compilation

L'ajout de .NET Framework contient une machine virtuelle, tout comme Java.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top