Quelle est la différence entre le fonctionnement interne de la machine virtuelle Java et le CLR de .NET?

Quelle est la différence entre le fonctionnement interne de la machine virtuelle Java et le CLR de .NET?

Peut-être un sharepoint départ serait-il, sont-ils fondamentalement les mêmes dans leurs environnements respectifs (Java> JVM> Code machine) (C #> CLR> IL).


Mise à jour: Plusieurs personnes ont fait allusion aux points que j’essayais de couvrir:

  1. Collecte des ordures
  2. Boxe / Unboxing
  3. Débogage JIT
  4. Génériques / Modèles
  5. N’hésitez pas à suggérer d’autres bons sujets qui différencient les deux.

@ George Mauer – cela semble très intéressant:

Déjà posté cette fois, mais voici une série d’entretiens avec le concepteur en chef de la langue c # Anders Hejlsberg.

Déjà posté cette fois, mais voici une série d’entretiens avec le concepteur en chef de la langue c # Anders Hejlsberg. Bien qu’il parle principalement des différences entre C # et Java, il plonge également dans les différences entre les machines virtuelles.

Cela devrait être un excellent fil conducteur.

L’une des plus grandes différences entre le CLR et la JVM est l’intégration native des génériques par le CLR.

Au lieu de cela, Java supprime les types génériques et la JVM ne peut travailler qu’avec des objects en sélectionnant les objects qu’il semble être des pseudo-génériques.

De là Je n’aurais pas pu dire mieux (enfin, à l’exception d’une guerre de flammes, c’est un endroit sans flammes :-)).

Bonjour,

Répondre à votre question semble périlleux en commençant une guerre des flammes, alors je vais procéder avec prudence.

Il existe un certain nombre de similitudes techniques fondamentales entre Java Runtime et Common Language Runtime, notamment une mémoire non récupérée, un langage intermédiaire (Microsoft IL par rapport à Java ByteCode), des bibliothèques système principales et la prise en charge de langages de haut niveau, la sécurité du code et déploiement.

Cependant, chacun de ces domaines «similaires» présente également un certain nombre de différences importantes et mineures, et décrire la plupart d’entre elles dépasse le cadre d’un simple post sur le Forum.

Je suggérerais de poser une question plus ciblée sur l’une des fonctionnalités d’exécution et les zones de composants (par exemple, la gestion de la mémoire, la compilation, les bibliothèques système, la sécurité, etc.) et nous pourrons ensuite fournir une réponse plus ciblée (par exemple, un blog, un article technique). , ou quelques livres).

Une différence essentielle réside dans le fait que la machine virtuelle Java est portable sur toutes les plates-formes et fonctionne sous Linux, Macintosh et de nombreux téléphones cellulaires et périphériques intégrés.

CLR s’exécute sur les plates-formes sockets en charge par Microsoft avec le projet Mono fournissant une prise en charge partielle des anciennes versions de CLR sur quelques autres.

En interne, cela signifie que les performances de la JVM varieront sur ces différentes plates-formes en fonction des capacités fournies par les plates-formes elles-mêmes.

La CLR et la JVM ont des objectives et des philosophies qui diffèrent plus que vous ne le pensez. En général, la machine virtuelle Java vise à optimiser un code de niveau supérieur plus dynamic, tandis que la CLR vous fournit davantage d’outils de bas niveau pour effectuer ce type d’optimisations vous-même.

Un bon exemple est l’allocation de stack. Sur le CLR, vous avez une allocation de stack explicite de types de valeur personnalisés. Sur la machine virtuelle Java, les seuls types personnalisés sont des types de référence, mais la machine virtuelle Java peut convertir les allocations de segment de mémoire en emstackments de stack dans certaines circonstances via l’parsing d’échappement.

Un autre exemple. En Java, les méthodes sont virtuelles par défaut. Sur C # au moins, ils ne le sont pas. Il est beaucoup plus difficile d’optimiser les appels de méthodes virtuelles car le code exécuté sur un site d’appels donné ne peut pas être déterminé de manière statique.

Sous le capot, leurs systèmes d’exécution sont très différents. La plupart des JVM (en particulier, Hotspot) démarrent avec un interpréteur de code bytecode et uniquement des parties du code JIT-compilées qui sont exécutées fortement, par exemple des boucles serrées. Ils peuvent également les recomstackr à chaque fois en utilisant les statistiques d’exécution collectées lors des exécutions précédentes pour piloter les optimisations. Cela permet d’intensifier les efforts d’optimisation des parties du programme qui en ont le plus besoin. Ceci s’appelle l’optimisation adaptative.

Le CLR comstack tout en une seule fois. Il effectue moins d’optimisations, car il a plus de code à comstackr et doit donc être rapide et parce qu’il ne dispose pas de statistiques sur les chemins d’exécution réels utilisés pour alimenter ses optimisations. Cette approche présente l’avantage très important de vous permettre de mettre en cache les résultats de compilation entre les processus, ce que fait CLR, contrairement à JVM.

Un grand pourcentage du code de la machine virtuelle Java Hotspot est dédié à ces optimisations adaptatives, ce qui place Java au même niveau de performance que le code natif pour la plupart des calculs à usage général au début des années 2000. C’est aussi ce qui fait de la JVM une cible décente pour les langages dynamics. J’exclus ici les développements plus récents du Runtime des langages dynamics et invokedynamic car je ne connais pas assez le DLR.

Miguel de Icaza mentionne ici :

Les programmeurs expérimentés du secteur remarqueront que ce qui précède ressemble beaucoup à Java et à la machine virtuelle Java. Ils ont raison, ce qui précède est comme Java.

Le langage CIL possède cependant une caractéristique introuvable en Java: il s’agit d’une représentation sous forme de code octet suffisamment puissante pour servir de cible à de nombreuses langues: du C ++ à C, en passant par Fortran et Eiffel, en passant par Lisp et Haskell, y compris Java, C # et JavaScript. et Visual Basic dans le mix.

J’aimerais avoir le temps d’aller plus en détail, mais pour les besoins de cet argument, ce qui précède suffira.

Les commentaires vont cependant dans certains détails, comme l’optimisation des appels de queue. Cependant, beaucoup ont changé depuis 2002: les langages CLR et JVM sont désormais ciblés par plusieurs langues. Mais néanmoins, ça vaut le coup de lire.

Comme Vinko l’a dit, les détails complets vont bien au-delà de la scope d’un message sur le forum. Les différences / similitudes se résument à ceci:

Il s’agit d’un “sandbox” d’environnement d’exécution qui inclut un compilateur “juste à temps” permettant de traduire les instructions du programme dans un langage intermédiaire (MSIL ou ByteCode) en code machine natif et de fournir une gestion automatique de la mémoire (nettoyage de la mémoire). Un ensemble de bibliothèques de classes, situées au-dessus des environnements d’exécution respectifs, fournit aux développeurs des abstractions de niveau supérieur pour simplifier les tâches de développement.

Les composants internes de la mise en œuvre effective de ces environnements d’exécution sont, pour la plupart, propriétaires de Microsoft et de Sun. Les algorithmes utilisés par les systèmes de récupération de place, par exemple, bien que leurs fonctionnalités techniques soient probablement similaires, diffèrent par leur mise en œuvre.

Pour autant que je sache, le .Net CLR dispose toujours d’une sécurité du code beaucoup plus flexible et puissante intégrée au moteur d’exécution, permettant des permissions et une politique d’exécution beaucoup plus précises.

Il existe également des différences dans la collecte des ordures. JVM utilise le collecteur de copie et Mark and sweep. Utilisateur .NET Copier le collecteur et Mark et compact (beaucoup plus difficile à mettre en œuvre).

Le type d’effacement mentionné par Flyswat est également important. JVM n’a pas la moindre idée des génériques et tout est object et perf associé. pénalité de boxe et de déballage. De plus, la reflection ne vous donnera pas d’informations génériques. CLR prend en charge les génériques de manière native.