136 votes

Java ' Machine virtuelle s et CLR

Comme une sorte de suivi de la question appelle différences entre bytecode MSIL et Java ?, quelle est la différence (importante) ou la similitude dans le fonctionnement de la Machine virtuelle Java par rapport à la façon dont le Common Language Runtime (CLR) .NET Framework fonctionne ?

En outre, le .NET framework CLR n’est une « machine virtuelle » ou il n’a pas les attributs d’une machine virtuelle ?

273voto

benjismith Points 8739

Il y a beaucoup de similitudes entre les deux mises en œuvre (et à mon avis: oui, ils sont tous les deux "machines virtuelles").

Pour une chose, ils sont à la fois basée sur la pile de l'ordinateur virtuel, avec pas de notion de "registres" comme nous avons l'habitude de voir dans un PROCESSEUR récent comme le x86 ou PowerPC. L'évaluation de toutes les expressions ((1 + 1) / 2) est réalisée en poussant des opérandes sur la "pile" et puis éclater ces opérandes hors de la pile chaque fois qu'une instruction (addition, division, etc) a besoin de consommer ces opérandes. Chaque instruction pousse ses résultats retour sur la pile.

C'est un moyen pratique de mettre en œuvre une machine virtuelle, parce qu'à peu près tous les CPU dans le monde a une pile, mais le nombre de registres est souvent différent (et certains registres sont spéciaux, et chaque instruction attend de ses opérandes dans des registres différents, etc).

Donc, si vous allez le modèle d'une machine abstraite, purement basée sur la pile modèle est une très bonne façon d'aller.

Bien sûr, de véritables machines ne fonctionnent pas de cette façon. Donc le compilateur JIT est chargé de l'exécution de "l'enregistrement" de bytecode opérations, essentiellement de la planification du réel registres du CPU pour contenir les opérandes et les résultats dès que possible.

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

Comme pour les différences...

Une différence intéressante entre les deux implémentations, c'est que le CLR comprend des instructions pour la création de types génériques, et ensuite pour l'application paramétrique spécialisations de ces types. Ainsi, au moment de l'exécution, le CLR considère une Liste<int> pour être un genre complètement différent à partir d'une Liste<String>.

Sous les couvertures, elle utilise le même langage MSIL de référence de type de spécialisations (donc une List<String> utilise la même mise en œuvre que d'une Liste de<Object>, avec différents type-jette à l'API de frontières), mais la valeur de chaque type utilise son propre mise en œuvre (List<int> produit complètement différent du code de List<double>).

En Java, les types génériques sont purement un compilateur truc. La JVM n'a aucune notion de classes qui ont le type des arguments, et il est impossible d'effectuer paramétrique spécialisations au moment de l'exécution.

À partir d'un point de vue pratique, cela signifie que vous ne pouvez pas la surcharge de méthodes de Java sur les types génériques. Vous ne pouvez pas avoir deux méthodes différentes, avec le même nom, qui diffèrent seulement sur le fait qu'ils acceptent une List<String> ou une Liste de<Date>. Bien sûr, depuis le CLR connaît paramétrique types, il n'a pas de problème de manipulation des méthodes surchargées sur le type générique de spécialisations.

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

D'autres différences importantes incluent:

  • Le CLR a des fermetures (mise en œuvre en C# délégués). La JVM ne pas.

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

  • Le CLR permet à l'utilisateur de code pour définir de nouveaux types de valeur (les structures), alors que la JVM fournit un fixe de collecte des types de valeur (byte, short, int, long, float, double, char, boolean) et seulement permet aux utilisateurs de définir une nouvelle référence-types (classes).

  • Le CLR fournit un soutien pour la déclaration et de la manipulation de pointeurs. Ceci est particulièrement intéressant, parce que les deux la JVM et le CLR employer stricte générationnel compactage garbage collector implémentations de leur mémoire de la stratégie de gestion. Dans des circonstances ordinaires, un strict de compactage GC a vraiment du mal avec les pointeurs, parce que quand vous déplacez une valeur à partir d'un emplacement mémoire à l'autre, tous les pointeurs (et des pointeurs de pointeurs) deviennent non valides. Mais le CLR fournit un "épinglage" mécanisme afin 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 "package", comme en témoigne la "protégés" mot-clé ou sans doute un BOCAL (c'est à dire Java ARchive), comme en témoigne être en mesure de spécifier un jar dans le classpath et de l'avoir traité comme un dossier de code. Dans le CLR, les classes sont regroupées en "assemblées", et le CLR fournit logique pour raisonner sur les et de manipuler des ensembles qui sont chargés dans des "domaines d'application", en offrant un sous-niveau de l'application sandbox pour l'allocation de mémoire et d'exécution du code).

  • Le CLR bytecode format (composé de MSIL des instructions et des métadonnées) a moins d'instructions types de la JVM. Dans la JVM, chaque opération unique (ajouter deux valeurs int, ajouter deux valeurs float, etc...) a sa propre instruction. Dans le CLR, toutes les instructions MSIL sont polymorphes (ajouter deux valeurs) et le compilateur JIT est responsable de déterminer les types des opérandes et de la création de la machine code. Je ne sais pas qui est la préférence de la stratégie. Les deux ont des compromis. Le HotSpot compilateur JIT, pour la JVM, peut utiliser une simple génération de code (il n'est pas nécessaire de déterminer l'opérande types, parce qu'ils sont déjà codées dans l'instruction), mais cela signifie qu'il a besoin d'un plus complexe bytecode format, avec plus d'instruction types.

J'ai été en utilisant Java (et d'admirer la JVM) pour une dizaine d'années maintenant.

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

25voto

RoadWarrior Points 11588

Votre première question est de comparer la JVM avec le .NET Framework - je suppose que vous avez fait pour comparer avec le CLR à la place. Si oui, je pense que vous pourriez écrire un petit livre sur ce (EDIT: regarde comme Benji a déjà :-)

Une différence importante est que le CLR est conçu pour être un langage neutre de l'architecture, à la différence de 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 de sécurité lorsque la mémoire natif est consulté et modifié, et aussi de gérer la composition des trains entre CLR basé sur des structures de données et des structures de données natif.

Pour répondre à votre deuxième question, le terme "machine virtuelle" est un terme plus ancien du monde matériel (par exemple, IBM virtualisation de la 360 dans les années 1960) qui ont utilisé pour signifier un matériel/logiciel d'émulation de la sous-jacentes de la machine pour accomplir le même genre de choses que VMWare ne.

Le CLR est souvent désigné comme un "moteur d'exécution". Dans ce contexte, c'est une mise en œuvre d'un IL Machine sur un x86. C'est aussi ce que la JVM ne, bien que l'on peut faire valoir qu'il y a une différence importante entre le CLR est polymorphe bytecode et la JVM est tapé bytecode.

Ainsi, le pédant réponse à votre deuxième question est "non". Mais il s'agit vraiment de la façon dont vous définir ces deux termes.

EDIT: encore Une différence entre la JVM et le CLR est que la JVM (version 6) est très réticents à libérer la mémoire allouée au système d'exploitation, même là où il peut.

Par exemple, supposons qu'un processus de JVM commence et alloue 25 MO de mémoire à partir du système d'exploitation initialement. Le code de l'application tente alors allocations qui nécessitent un supplément de 50 MO. La JVM va allouer un supplément de 50 MO à partir du système d'exploitation. Une fois le code de l'application a cessé d'utiliser cette mémoire, c'est le garbage collector et la taille de segment JVM va diminuer. Cependant, la JVM ne sera libéré que la répartition de la mémoire du système d'exploitation dans certaines circonstances très particulières. Sinon, pour le reste de la durée de vie des processus de la mémoire restera alloué.

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 publié la mémoire une fois que le tas avait diminué.

11voto

James Schek Points 11070

Plus de détails sur les différences peuvent être trouvés à partir de nombreux universitaires et de sources privées. Une fois que le bon exemple est CLR Choix de Conception.

Quelques exemples spécifiques comprennent:

  • Certains de bas niveau opperands sont typées comme "ajouter les deux ints" lorsque CLR utilise un polymorphe de l'opérande. (c'est à dire fadd/iadd/ladd vs juste ajouter)
  • Actuellement, la JVM ne plus agressif profilage d'exécution et l'optimisation (c'est à dire Hotspot). CLR actuellement ne optimisations JIT, mais pas de runtime optimization (c'est à dire remplacer le code pendant que vous êtes en cours d'exécution).
  • CLR n'est pas inline méthodes virtuelles, JVM ne...
  • Support pour les types de valeur dans le CLR-delà de la simple "primitives".

9voto

Allain Lalonde Points 28717

Le Common Language Runtime et la JVM sont les deux machines virtuelles.

Le .NET Framework et l’environnement d’exécution Java sont le groupement des machines virtuelles et leurs bibliothèques. Sans les bibliothèques, les machines virtuelles sont assez inutiles.

-11voto

Diones Points 552

Ce n'est pas une machine virtuelle, l' .net framework compile les assemblées en binaire natif au moment de la première manche:

En informatique, le juste-à-temps de compilation (JIT), aussi connu comme la traduction dynamique, est une technique visant à améliorer les performances d'exécution d'un programme d'ordinateur. JIT s'appuie sur deux idées antérieures dans des environnements d'exécution: le bytecode de la compilation et de la compilation dynamique. Il convertit le code au moment de l'exécution avant d'exécuter en mode natif, par exemple bytecode en code machine natif. L'amélioration des performances sur les interprètes provient de la mise en cache des résultats de la traduction des blocs de code, et non pas simplement la réévaluation de chaque ligne ou opérande à chaque fois qu'il est atteint (voir langage Interprété). Il a aussi des avantages sur statiquement à la compilation le code au moment du développement, car il peut recompiler le code si cela se trouve à être avantageux, et peut être en mesure d'appliquer les garanties de sécurité. Ainsi, JIT peut combiner les avantages de l'interprétation et de la statique (à l'avance) de la compilation.

Aujourd'hui, plusieurs environnements d'exécution, tels que Microsoft .NET Framework, la plupart des implémentations de Java, et, plus récemment, Actionscript 3, reposent sur la compilation JIT pour la grande vitesse d'exécution de code.

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

L'addition .NET framework contient une machine virtuelle, tout comme Java.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X