Comme une sorte de suivi de la question intitulée Différences entre MSIL et le bytecode Java? , quelles sont les (principales) différences ou similitudes dans le fonctionnement de la machine virtuelle Java par rapport à laFramework .NET Common Language Runtime (CLR) fonctionne?
Aussi, est le Framework .NET CLR une "machine virtuelle" ou n'a-t-il pas les attributs d'une machine virtuelle?
Réponses:
Il y a beaucoup de similitudes entre les deux implémentations (et à mon avis: oui, ce sont toutes les deux des "machines virtuelles").
D'une part, ce sont toutes deux des VM basées sur la pile, sans notion de «registres» comme nous avons l'habitude de voir dans un processeur moderne comme le x86 ou PowerPC. L'évaluation de toutes les expressions ((1 + 1) / 2) est effectuée en poussant des opérandes sur la "pile", puis en faisant sortir ces opérandes de la pile chaque fois qu'une instruction (ajouter, diviser, etc.) a besoin de consommer ces opérandes. Chaque instruction repousse ses résultats sur la pile.
C'est un moyen pratique d'implémenter une machine virtuelle, car à peu près tous les processeurs du monde ont une pile, mais le nombre de registres est souvent différent (et certains registres sont à usage spécial, et chaque instruction attend ses opérandes dans différents registres, etc. ).
Donc, si vous voulez modéliser une machine abstraite, un modèle purement basé sur la pile est une très bonne solution.
Bien sûr, les vraies machines ne fonctionnent pas de cette façon. Ainsi, le compilateur JIT est chargé d'effectuer "l'enregistrement" des opérations de bytecode, en planifiant essentiellement les registres CPU réels pour contenir les opérandes et les résultats chaque fois que possible.
Donc, je pense que c'est l'un des plus grands points communs entre le CLR et la JVM.
Quant aux différences ...
Une différence intéressante entre les deux implémentations est que le CLR comprend des instructions pour créer des types génériques, puis pour appliquer des spécialisations paramétriques à ces types. Ainsi, au moment de l'exécution, le CLR considère un List <int> comme un type complètement différent d'un List <String>.
Sous les couvertures, il utilise le même MSIL pour toutes les spécialisations de type de référence (donc un List <String> utilise la même implémentation qu'un List <Object>, avec des types différents 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>).
En Java, les types génériques sont purement une astuce du compilateur. La machine virtuelle Java n'a aucune idée des classes qui ont des arguments de type et elle ne peut pas effectuer de spécialisations paramétriques au moment de 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, différant uniquement selon qu'elles acceptent une List <String> ou une List <Date>. Bien sûr, puisque le CLR connaît les types paramétriques, il n'a aucun problème à gérer les méthodes surchargées sur les spécialisations de types génériques.
Au quotidien, c'est la différence que je remarque le plus entre le CLR et la JVM.
D'autres différences importantes incluent:
Le CLR a des fermetures (implémentées en tant que délégués C #). La JVM ne prend en charge les fermetures que depuis Java 8.
Le CLR a des coroutines (implémentées avec le mot clé C # 'yield'). La JVM ne le fait pas.
Le CLR permet au code utilisateur de définir de nouveaux types de valeur (structs), tandis que la JVM fournit une collection fixe de types de valeur (byte, short, int, long, float, double, char, boolean) et permet uniquement aux utilisateurs de définir une nouvelle référence- types (classes).
Le CLR prend en charge la déclaration et la manipulation des pointeurs. Ceci est particulièrement intéressant car la JVM et le CLR utilisent des implémentations strictes de ramasse-miettes de compactage générationnel comme stratégie de gestion de la mémoire. Dans des circonstances ordinaires, un GC compactage strict a vraiment du mal avec les pointeurs, car lorsque vous déplacez une valeur d'un emplacement mémoire à un autre, tous les pointeurs (et pointeurs vers des pointeurs) deviennent invalides. Mais le CLR fournit un mécanisme "d'épinglage" afin que les développeurs puissent déclarer un bloc de code dans lequel le CLR n'est pas autorisé à déplacer certains pointeurs. C'est très pratique.
La plus grande unité de code dans la JVM est soit un 'package' comme en témoigne le mot-clé 'protected' ou sans doute un JAR (c'est-à-dire Java ARchive) comme en témoigne la possibilité de spécifier un fichier jar dans le chemin de classe et de le traiter comme un dossier du code. Dans le CLR, les classes sont agrégées dans des «assemblys» et le CLR fournit une logique de raisonnement et de manipulation des assemblys (qui sont chargés dans «AppDomains», fournissant des sandbox au niveau des sous-applications pour l'allocation de mémoire et l'exécution de code).
Le format de bytecode CLR (composé d'instructions MSIL et de métadonnées) a moins de types d'instructions que la JVM. Dans la JVM, 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 responsable de la détermination des types d'opérandes et de la création du code machine approprié. Je ne sais pas quelle est la stratégie de préférence. Les deux ont des compromis. Le compilateur HotSpot JIT, pour la JVM, peut utiliser un mécanisme de génération de code plus simple (il n'a pas besoin de déterminer les types d'opérandes, car ils sont déjà codés dans l'instruction), mais cela signifie qu'il a besoin d'un format de bytecode plus complexe, avec plus de types d'instructions.
J'utilise Java (et j'admire la JVM) depuis une dizaine d'années maintenant.
Mais, à mon avis, le CLR est maintenant l'implémentation supérieure, à presque tous les égards.
la source
Votre première question est de comparer la JVM avec le .NET Framework - je suppose que vous vouliez plutôt comparer avec le CLR. Si c'est le cas, je pense que vous pourriez écrire un petit livre à ce sujet ( EDIT: on dirait 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 haut niveau 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, et également gérer le rassemblement entre les structures de données CLR et les structures de données natives.
Pour répondre à votre deuxième question, le terme «machine virtuelle» est un terme plus ancien du monde matériel (par exemple la virtualisation de la 360 par IBM dans les années 1960) qui signifiait autrefois une émulation logicielle / matérielle de la machine sous-jacente pour accomplir le même type de ce que fait VMWare.
Le CLR est souvent appelé "moteur d'exécution". Dans ce contexte, il s'agit d'une implémentation d'une IL Machine sur un x86. C'est également ce que fait la JVM, bien que vous puissiez affirmer qu'il existe une différence importante entre les bytecodes polymorphes du CLR et les bytecodes typés de la JVM.
La réponse pédante à votre deuxième question est donc «non». Mais cela dépend vraiment de la façon dont vous définissez ces deux termes.
EDIT: Une autre différence entre la JVM et le CLR est que la JVM (version 6) est très réticente à libérer la mémoire allouée au système d'exploitation, même là où elle le peut.
Par exemple, disons 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 les allocations qui nécessitent 50 Mo supplémentaires. La JVM allouera 50 Mo supplémentaires du système d'exploitation. Une fois que le code d'application a cessé d'utiliser cette mémoire, il est récupéré et la taille du tas JVM diminuera. Cependant, la JVM ne libérera la mémoire allouée du système d'exploitation que dans certaines circonstances très spécifiques . Sinon, pour le reste de la durée de vie du processus, cette mémoire restera allouée.
Le CLR, d'autre part, libère 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 avait diminué.
la source
Le CLR et la JVM sont tous deux des machines virtuelles.
Le .NET Framework et l'environnement Java Runtime sont le regroupement des machines virtuelles respectives et de leurs bibliothèques. Sans bibliothèques, les VM sont plutôt inutiles.
la source
Plus de détails sur les différences peuvent être trouvés à partir de diverses sources universitaires et privées. Un bon exemple est CLR Design Choices .
Quelques exemples spécifiques incluent:
la source
Ce n'est pas une machine virtuelle, le framework .net compile les assemblys en binaire natif au moment 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 bytecode et la compilation dynamique. Il convertit le code au moment de l'exécution avant de l'exécuter de manière native, par exemple le bytecode en code machine natif. L'amélioration des performances par rapport aux interpréteurs provient de la mise en cache des résultats de la traduction de blocs de code, et pas simplement 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 être en mesure d'appliquer des garanties de sécurité.
Plusieurs environnements d'exécution modernes, tels que .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 à grande vitesse.
Source: http://en.wikipedia.org/wiki/Just-in-time_compilation
L'ajout du framework .NET contient une machine virtuelle, tout comme Java.
la source