La Machine virtuelle Java et CLR

comme une sorte de suivi à la question appelée différences entre MSIL et Java bytecode? , quelles sont les différences (majeures) ou similitudes entre le fonctionnement de la Machine virtuelle Java et le fonctionnement du .net Framework Common Language Runtime (CLR)?

aussi, est-ce que le .net framework CLR est une "machine virtuelle" ou n'a-t-il pas les attributs d'une machine virtuelle?

126
demandé sur Community 2009-01-17 20:06:49

5 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").

pour une chose, ils sont tous les deux des VM à base de pile, sans aucune notion de" registres " comme nous sommes habitués à voir dans un CPU moderne comme le x86 ou le PowerPC. L'évaluation de toutes les expressions ((1 + 1) / 2) est effectuée en poussant les opérandes sur la "pile" et en enlevant ensuite ces opérandes de la pile chaque fois qu'une instruction (add, divide, etc) a besoin pour consommer les opérandes. Chaque instruction repousse ses résultats sur la pile.

c'est un moyen commode pour implémenter une machine virtuelle, parce que presque tous les CPU dans le monde ont une pile, mais le nombre de registres est souvent différent (et certains registres sont spéciaux, et chaque instruction attend ses opérandes dans différents registres, etc).

donc, si vous allez modéliser une machine abstraite, un modèle purement basé sur la pile est une jolie une bonne façon d'aller.

bien sûr, les vraies machines ne fonctionnent pas de cette façon. Le compilateur JIT est donc chargé d'effectuer "l'enregistrement" des opérations de bytecode, programmant 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 points communs les plus importants entre la CLR et la JVM.

comme pour les différences...

une différence intéressante entre les deux implémentations, le CLR inclut des instructions pour créer des types génériques, puis pour appliquer des spécialisations paramétriques à ces types. Ainsi, à l'exécution, le CLR considère Qu'une liste est un type complètement différent d'une liste.

sous les couvertures, il utilise le même MSIL pour toutes les spécialisations de type de référence (donc une liste utilise la même implémentation qu'une liste, avec différents types-casts aux limites de L'API), mais chaque value-type utilise sa propre implémentation (List < int> génère un code complètement différent de List).

en Java, les types génériques sont purement un truc de compilateur. La JVM ne sait pas quelles classes ont des arguments de type, et elle est incapable d'effectuer des 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 les types génériques. Vous ne pouvez pas avoir deux méthodes différentes, avec le même nom, ne diffèrent que sur le point de savoir s'ils acceptent une liste ou une liste. Bien sûr, puisque le CLR connaît les types paramétriques, il n'a aucun problème de méthodes de manipulation surchargées sur les spécialisations de type génériques.

sur une base quotidienne, c'est la différence que je remarque le plus entre le CLR et le JVM.

autres différences importantes:

  • la CLR a des fermetures (mises en œuvre en tant que délégués C#). La JVM ne supporte les fermetures que depuis Java 8.

  • Le CLR a coroutines (mis en œuvre avec le C# 'rendement' mot-clé). La JVM ne pas.

  • le CLR permet au code utilisateur de définir de nouveaux types de valeurs (structures), tandis que la JVM fournit une collection fixe de types de valeurs (byte, short, int, long, float, double, char, boolean) et ne permet aux utilisateurs de définir de nouveaux types de référence (classes).

  • le CLR fournit un support pour la déclaration et la manipulation des pointeurs. Ceci est d'autant plus intéressant que la JVM et la CLR utilisent des implémentations de collecteurs de déchets de compactage générationnels stricts comme stratégie de gestion de la mémoire. Dans des circonstances ordinaires, un GC compacting strict a un temps très difficile avec les pointeurs, parce que lorsque vous déplacez une valeur d'un emplacement de mémoire à un autre, tous les pointeurs (et les pointeurs vers les pointeurs) deviennent invalide. Mais le CLR fournit un mécanisme de" pinning " de sorte que les développeurs peuvent déclarer un bloc de code dans lequel le CLR n'est pas autorisé à déplacer certains pointeurs. Il est très pratique.

  • la plus grande unité de code dans la JVM est soit un "paquet" tel que démontré par le mot-clé "protégé", soit sans doute un JAR (C'est-à-dire Java ARchive) tel que démontré en étant capable de spécifier un jar dans classpath et de le faire traiter comme un dossier de code. Dans le CLR, les classes sont agrégés en "assemblages", et le CLR fournit une logique pour raisonner et manipuler les assemblages (qui sont chargés dans des" AppDomains", fournissant des bacs à sable au niveau des sous-Applications pour l'allocation de la mémoire et l'exécution du code).

  • le format CLR bytecode (composé d'instructions et de métadonnées MSIL) comporte moins de types d'instructions que le JVM. Dans la JVM, chaque opération unique (ajout de deux valeurs int, ajout de deux valeurs float, etc.) a sa propre valeur unique instruction. Dans le CLR, toutes les instructions MSIL sont polymorphiques (ajouter deux valeurs) et le compilateur JIT est responsable de déterminer les types d'opérandes et de créer le code machine approprié. Je ne sais pas qui est la préférence de la stratégie. Les deux ont des compromis. Le compilateur HotSpot JIT, pour le 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érande, car ils sont déjà encodés dans l'instruction), mais cela signifie qu'il a besoin d'un plus format complexe de bytecode, avec plus de types d'instruction.

J'utilise Java (et j'admire la JVM) depuis une dizaine d'années maintenant.

mais, à mon avis, le CLR est maintenant la mise en œuvre supérieure, dans presque tous les sens.

266
répondu benjismith 2015-04-10 23:13:16

votre première question Est de comparer la JVM avec le.Net Framework - je suppose que vous avez réellement voulu comparer avec le CLR à la place. Si c'est le cas, je pense que vous pourriez écrire un petit livre à ce sujet ( EDIT: ressemble à Benji a déjà: -)

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

une autre différence importante est que le PLC a été spécifiquement 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é lorsque la mémoire native est accessible et modifiée, et aussi gérer la formation entre les structures de données basées sur le 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 IBM du 360 dans les années 1960) qui signifiait émulation logicielle / matérielle de la machine sous-jacente pour accomplir le même genre de choses que VMWare fait.

le CLR est souvent appelé"moteur d'exécution". Dans ce contexte, c'est une implémentation D'une Machine IL sur un x86. C'est également ce que fait la JVM, même si vous pouvez dire qu'il y a une différence importante entre les bytecodes polymorphes du CLR et les bytecodes typés par la JVM.

ainsi la réponse pédante à votre deuxième la question est "non". Mais il s'agit vraiment de la façon dont vous 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 à libérer la mémoire allouée vers le système d'exploitation, même si 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 ensuite, tente des allocations qui nécessitent un supplément de 50 Mo. 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 collecté et la taille du tas JVM diminuera. Toutefois, la JVM ne libérera la mémoire du système d'exploitation attribuée que dans certaines circonstances très spécifiques . Sinon, pour le reste de la durée de vie du processus, cette mémoire restera attribué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é.

25
répondu RoadWarrior 2017-05-23 11:54:41

on peut trouver plus de détails sur les différences dans diverses sources universitaires et privées. Un bon exemple est CLR Design Choices .

quelques exemples spécifiques comprennent:

  • certains opperands de bas niveau sont typés comme "add two ints" où comme CLR utilise un opérande polymorphique. (c'est à dire fadd/iadd/ladd vs juste ajouter)
  • actuellement, la JVM effectue un profilage d'exécution plus agressif et optimisation (c'est à dire Hotspot). CLR effectue actuellement des optimisations JIT, mais pas des optimisations d'exécution (c'est-à-dire remplacer le code pendant que vous exécutez).
  • CLR n'est pas inline méthodes virtuelles, JVM ne...
  • Support pour les types de valeurs dans le CLR au-delà des "primitives".
11
répondu James Schek 2009-01-27 23:06:44

la CLR et la JVM sont toutes deux des machines virtuelles.

le Framework .NET et L'environnement Java Runtime sont le bundling des VM respectifs et de leurs bibliothèques. Sans bibliothèques, les VMs sont inutiles.

9
répondu Allain Lalonde 2009-01-17 17:10:15

ce n'est pas une machine virtuelle, le .net framework compile les assemblages en binaire natif au moment de la première exécution:

en informatique, la compilation juste-à-temps (JIT), également connue sous le nom de traduction dynamique, est une technique pour améliorer les performances d'exécution d'un programme informatique. JIT s'appuie sur deux idées précédentes dans les environnements d'exécution: la compilation bytecode et la compilation dynamique. Il convertit le code à l'exécution avant de l'exécuter nativement, par exemple bytecode dans le code machine natif. L'amélioration de la performance par rapport aux interprètes provient de la mise en cache des résultats de la traduction de blocs de code, et non pas simplement de réévaluer chaque ligne ou opérande chaque fois qu'elle est respectée (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'imposer des garanties de sécurité. Ainsi, JIT peut combiner certains des avantages de interprétation et compilation statique (en amont).

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

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

additionner .net framework contient une machine virtuelle, tout comme Java.

-11
répondu Diones 2009-01-17 17:32:45