Qu'est-ce qui rend JVM si polyvalent pour prendre en charge autant de langages JVM?

18

JVM prend en charge de nombreux langages autres que Java comme Groovy,Clojure,Scalaetc., qui sont des langages fonctionnels contrairement à Java (je fais référence à Java avant la version 8Lambda'sils ne sont pas pris en charge) qui ne prend pas en charge les capacités fonctionnelles. À un niveau élevé, ce qui rend la JVM si polyvalente qu'elle peut prendre en charge les langages orientés objet et fonctionnels?

Geek
la source
"Groovy, Clojure, Scala etc qui sont fonctionnels". Certains d'entre eux sont plus fonctionnels que d'autres. J'utiliserais une balance avec Groovy le moins fonctionnel et Clojure le plus, avec Scala au milieu.
Vorg van Geir

Réponses:

37

Par rapport aux autres VM, la JVM n'est en fait pas particulièrement polyvalente . Il prend directement en charge OO de type statique. Pour tout le reste, vous devez voir quelles parties vous pouvez utiliser et comment vous pouvez construire tout ce dont votre langue a besoin par-dessus ces parties.

Par exemple, jusqu'à ce que Java 7 introduise le invokedynamicbytecode, il était très difficile d'implémenter un langage OO typé dynamiquement sur la JVM - vous deviez utiliser des solutions de contournement complexes qui étaient mauvaises pour les performances et entraînaient des traces de pile horriblement gonflées.

Et pourtant, un tas de langages dynamiques (Groovy, Jython, JRuby entre autres) ont été implémentés sur la JVM avant cela.

Non pas parce que la JVM est si polyvalente, mais parce qu'elle est si répandue et parce qu'elle a des implémentations très matures, bien prises en charge et très performantes.

Et, peut-être encore plus important, car il existe une énorme quantité de code Java qui fait à peu près n'importe quoi, et si votre langage s'exécute sur la JVM, vous pouvez facilement offrir des fonctionnalités pour l'intégrer à ce code. Fondamentalement, l'exécution de votre langage sur la JVM est la version du 21e siècle de l'interopérabilité avec C.

Michael Borgwardt
la source
Bonne réponse (+1). Le dernier point que vous mentionnez est à mon humble avis également responsable de la popularité de Java en tant que langage: au final, avoir une énorme quantité de code que vous pouvez réutiliser gratuitement peut vous faire gagner beaucoup plus de temps que de pouvoir utiliser le langage le plus récent et le plus à la mode. Caractéristiques.
Giorgio
4

La JVM a été écrite pour agir essentiellement comme un CPU, il y a un ensemble d'instructions, un peu comme un assemblage, que la VM exécute appelé bytecodes. Si vous pouvez écrire un compilateur qui génère un ensemble valide de bytecodes, la JVM peut les exécuter.

Wikipedia a une liste des bytecodes:

http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

ainsi qu'une explication de la façon dont la JVM charge les codes d'octets:

http://en.wikipedia.org/wiki/Java_virtual_machine

En utilisant les bytecodes de style d'invocation, un langage fonctionnel peut exécuter du code, quelle que soit la source. De plus, avec l'ajout de invokevirtual, les implémentations de langage comme jruby ont donné une certaine flexibilité dans leur fonctionnement.

sasbury
la source
1
La même chose est vraie pour toutes les autres machines virtuelles: la machine virtuelle YARV Ruby, la machine Rubinius Ruby, la machine virtuelle CPython (qui, après tout, est antérieure à la JVM), Parrot, diverses machines virtuelles Smalltalk et Lisp, et bien sûr la Pascal P- Système de code, après quoi la JVM est modélisée.
Jörg W Mittag
D'accord, la JVM n'est certainement pas la première machine virtuelle sur le marché. Je pense que la JVM est populaire pour d'autres langages car Java est populaire, la VM est activement développée et bien documentée.
sasbury
2

J'ajouterai que la JVM prend en charge un modèle de mémoire ( JMM ) bien défini et assez décent, ce qui signifie une bonne prise en charge d'un comportement de threading cohérent (bien que de bas niveau). Il dispose également d'un puissant compilateur Just In Time (plus utile pour les langages dynamiques grâce à MethodHandles et invokedynamic).

Le dernier mais non le moindre est le sous-système Garbage Collection de la JVM qui (avec le bon réglage) gère la mémoire pour vous quelle que soit la langue du dessus.

Martijn Verburg
la source
Le JMM est l'une de mes choses les moins préférées à propos de Java. Je suis un fan des données effectivement immuables (par exemple, les tableaux dont le contenu ne changera jamais après être visible pour les autres threads), mais étant donné une déclaration comme someField = new int[]{42};les seules façons de s'assurer que tout thread qui voit le nouveau tableau verra la valeur 42 doivent soit faire le champ finalou volatile. Si le champ est généré paresseusement mais accédé fréquemment, le faire finalne fonctionnera pas et le rendre volatilepeut imposer une pénalité de synchronisation inutile à chaque fois qu'il est accédé. Même dans le modèle .NET le plus lâche ...
supercat
... le code peut demander que le remplissage du tableau se produise avant le stockage de la référence. Les autres threads qui lisent le champ peuvent ou non voir la référence au nouveau tableau, mais sans aucun coût pour eux-mêmes, ils seront assurés que s'ils voient le nouveau tableau, ils verront son contenu.
supercat
1

L'élément clé est la séparation de la compilation de la phase d'exécution. Par cela, il est possible d'écrire d'autres compilateurs compilant d'autres langues en bytecode.

Le bytecode agit comme le code machine d'un CPU - vous avez toutes les petites opérations nécessaires pour exécuter un programme - vous pouvez obtenir une variable, faire des calculs dessus, avoir des opérations conditionnelles, etc.

Java n'est pas non plus spécial. En Java, l'existence de plusieurs langages n'était même pas un objectif de conception, contrairement aux autres machines virtuelles. Pour .Net CIL de Microsoft, la capacité d'exécuter plusieurs langues (C #, VB.Net, ...) était un élément clé de la conception, ainsi que le ParrotVM du projet Perl6 visant à être une machine virtuelle générique.

Pour le plaisir, j'ai créé une fois une preuve que même le moteur Zend de PHP le permettrait.

Et franchement, ce n'est pas quelque chose de nouveau - même sur du vrai matériel, vous pouvez exécuter plusieurs langues - c'est-à-dire C ou Fortran.

La différence par rapport à cette séparation de la compilation et de l'exécution sont les interprètes clssic, comme certaines formes de Basic, les scripts shell, etc. ils fonctionnent souvent de manière à exécuter le code plus ou moins ligne par ligne sans le mettre sous une forme immédiate entre.

johannes
la source
1

La machine virtuelle Java est la première machine virtuelle que je connaisse qui combine la récupération de place, les performances et un modèle sandbox fonctionnel. L'émergence de nombreux langages pour prendre en charge la JVM n'est probablement pas tant le résultat de sa "polyvalence", mais plutôt le fait que le langage Java manque de fonctionnalités importantes que les gens veulent dans un langage de programmation. Par exemple, alors que la plupart des langages machine ont seulement une demi-douzaine de types de données (par exemple, octet, demi-mot, mot, double mot, flottant simple précision et flottant double précision), la grande majorité des langages de programmation permettent au code d'utiliser un nombre arbitraire de types de données définis par l'utilisateur. La machine virtuelle Java reconnaît quelques types primitifs similaires à ceux d'une machine typique, plus un autre type: la référence d'objet promiscuous. Le langage Java reconnaît également ces primitives, et références aux objets promiscuité. Bien qu'une variable puisse être contrainte de ne pas contenir de références à tout ce qui n'est pas une classe particulière, le langage ne fait aucune distinction entre les types de champs de type suivantsList<String>qui pourraient être détenus par MyThingclasse d' instance MyClass:

  • Une référence à quelque chose de code sait être une implémentation immuable de List<String>

  • Une référence à une instance d'un type de liste mutable qui ne sera jamais exposée à quoi que ce soit qui pourrait la muter.

  • Une référence à une liste mutable à laquelle, sauf lors de l'exécution des MyThingsméthodes de, aucune autre référence ne pourrait exister nulle part dans l'univers.

  • Une référence à une liste mutable qui appartient à un autre objet , que cet autre objet aimerait MyThingutiliser d'une manière ou d'une autre.

  • Une référence à une liste mutable qui MyThingpossède, mais qu'elle a également exposée à d'autres objets afin qu'ils puissent faire quelque chose avec elle.

Même si tous ces champs peuvent avoir un type List<String>, ils contiennent des choses très différentes. Un langage expressif pourrait permettre une distinction entre ces significations, mais Java ne le permet pas. Puisqu'un langage peut attacher du sens à de telles choses (au moins en dehors des contextes génériques) et s'exécuter sur la JVM, cela laisse beaucoup de place aux langages ciblés par la JVM pour exprimer des concepts que Java ne peut pas.

supercat
la source