Was macht JVM so vielseitig, um so viele JVM-Sprachen zu unterstützen?

18

JVM unterstützt so viele andere Sprachen als Java wie Groovy,Clojure,Scalaetc, die andere funktionale Sprachen als Java sind (ich beziehe mich auf Java vor Version 8, wo sie Lambda'snicht unterstützt werden), die keine funktionalen Fähigkeiten unterstützen können sowohl objektorientierte als auch funktionale Sprachen unterstützen?

Aussenseiter
quelle
"Groovy, Clojure, Scala etc die funktionieren". Einige davon sind funktionaler als andere. Ich würde eine Skala mit Groovy am wenigsten funktionieren und Clojure am meisten, mit Scala in der Mitte.
Vorg van Geir

Antworten:

37

Im Vergleich zu anderen VMs ist die JVM nicht besonders vielseitig . Es unterstützt direkt statisch typisierte OO. Für alles andere müssen Sie sehen, welche Teile Sie verwenden können und wie Sie alles andere aufbauen können, das Ihre Sprache über diesen Teilen benötigt.

Bis Java 7 den invokedynamicBytecode einführte , war es beispielsweise sehr schwierig, eine dynamisch typisierte OO-Sprache in der JVM zu implementieren. Sie mussten komplexe Problemumgehungen verwenden, die die Leistung beeinträchtigten und zu fürchterlich aufgeblähten Stack-Traces führten.

Davor waren jedoch einige dynamische Sprachen (Groovy, Jython, JRuby ua) in der JVM implementiert.

Nicht, weil die JVM so vielseitig ist, sondern weil sie so weit verbreitet ist und sehr ausgereifte, gut unterstützte und leistungsstarke Implementierungen aufweist.

Und, vielleicht noch wichtiger, weil es eine riesige Menge von Java-Code gibt, die so ziemlich alles macht, und wenn Ihre Sprache in der JVM ausgeführt wird, können Sie leicht Funktionen anbieten, die sich in diesen Code integrieren lassen. Grundsätzlich ist es die Version des 21. Jahrhunderts, die Interoperabilität mit C bietet, wenn Ihre Sprache in der JVM ausgeführt wird.

Michael Borgwardt
quelle
Gute Antwort (+1). Der letzte Punkt, den Sie erwähnen, ist, dass IMHO auch für die Beliebtheit von Java als Sprache verantwortlich ist: Wenn Sie eine große Menge an Code kostenlos wiederverwenden können, können Sie viel mehr Zeit sparen, als wenn Sie die neueste und modernste Sprache verwenden können Eigenschaften.
Giorgio
4

Die JVM wurde so geschrieben, dass sie sich im Grunde genommen wie eine CPU verhält. Es gibt eine Reihe von Anweisungen, ähnlich einer Assembly, die von der VM ausgeführt werden und Bytecodes genannt werden. Wenn Sie einen Compiler schreiben können, der einen gültigen Satz von Bytecodes generiert, kann die JVM diese ausführen.

Wikipedia hat eine Liste der Bytecodes:

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

sowie eine Erklärung, wie die JVM die Byte-Codes lädt:

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

Durch die Verwendung der aufrufbaren Bytecodes kann eine funktionale Sprache Code ausführen, unabhängig davon, wie die Quelle aussieht. Darüber hinaus haben Sprachimplementierungen wie jruby durch die Hinzufügung von invokevirtual eine gewisse Flexibilität hinsichtlich ihrer Funktionsweise verliehen.

Sasbury
quelle
1
Dasselbe gilt für alle anderen VMs: die YARV-Ruby-VM, die Rubinius-Ruby-VM, die CPython-VM (die immerhin älter ist als die JVM), Parrot, verschiedene Smalltalk- und Lisp-VMs und natürlich die Pascal-P- Codesystem, nach dem die JVM modelliert wird.
Jörg W Mittag
Einverstanden, die JVM ist definitiv nicht die erste VM da draußen. Ich denke, dass die JVM für andere Sprachen beliebt ist, weil Java beliebt ist, die VM aktiv entwickelt und gut dokumentiert ist.
Sasbury
2

Ich füge hinzu, dass die JVM ein gut definiertes und anständiges Speichermodell ( JMM ) unterstützt, was eine gute Unterstützung für konsistentes Threading-Verhalten (wenn auch auf niedriger Ebene) bedeutet. Es hat auch einen leistungsstarken Just In Time- Compiler (nicht mehr nützlich für dynamische Sprachen dank MethodHandles und invokedynamic).

Last but not least gibt es das Garbage Collection-Subsystem der JVM , das (mit der richtigen Abstimmung) den Arbeitsspeicher für Sie verwaltet, unabhängig von der Sprache, in der Sie sich befinden.

Martijn Verburg
quelle
Das JMM ist eines meiner am wenigsten bevorzugten Dinge in Java. Ich bin ein Fan von effektiv unveränderlichen Daten (z. B. Arrays, deren Inhalt sich nie ändert, nachdem sie für andere Threads sichtbar sind), aber ich habe eine Anweisung erhalten someField = new int[]{42};, mit der ich sicherstellen kann, dass jeder Thread, der das neue Array sieht, den Wert sieht 42 sollen entweder das Feld machen finaloder volatile. Wenn das Feld träge generiert wird, auf das jedoch häufig zugegriffen finalwird, funktioniert es nicht und es volatilekann bei jedem Zugriff zu einer unnötigen Synchronisationsstrafe führen. In selbst dem lockersten .NET-Modell ...
Supercat
... Code kann anfordern, dass die Auffüllung des Arrays vor dem Speichern der Referenz erfolgt. Andere Threads, die das Feld lesen, sehen möglicherweise den Verweis auf das neue Array oder nicht, können sich jedoch ohne weiteres sicher sein, dass sie den Inhalt des neuen Arrays sehen, wenn sie es sehen.
Supercat
1

Das Schlüsselelement dabei ist die Trennung der Kompilierung von der Ausführungsphase. Auf diese Weise ist es möglich, andere Compiler zu schreiben, die andere Sprachen zu Bytecode kompilieren.

Bytecode dort verhält sich ähnlich wie der Maschinencode einer CPU - Sie haben alle kleinen Operationen, die zum Ausführen eines Programms erforderlich sind - Sie können eine Variable abrufen, rechnen, bedingte Operationen ausführen usw.

Java ist auch nichts Besonderes. In Java war das Vorhandensein mehrerer Sprachen im Gegensatz zu anderen VMs nicht einmal ein Entwurfsziel. Für Microsoft .Net CIL war die Möglichkeit, mehrere Sprachen (C #, VB.Net, ...) auszuführen, ein wichtiges Designelement, und auch ParrotVM aus dem Perl6-Projekt sollte eine generische VM sein.

Zum Spaß habe ich mal einen Beweis erstellt, dass selbst die Zend Engine von PHP das zulässt.

Und ehrlich gesagt ist dies nichts Neues - selbst auf echter Hardware können Sie mehrere Sprachen ausführen - z. B. C oder Fortran.

Der Unterschied zu dieser Trennung von Kompilierung und Ausführung besteht darin, dass CLSSIC-Interpreter, wie einige Formen von Basic, Shell-Skripten usw., häufig so arbeiten, dass sie Code mehr oder weniger zeilenweise ausführen, ohne ihn in eine unmittelbare Form zu bringen zwischen.

johannes
quelle
1

Die JVM ist die erste virtuelle Maschine, deren kombinierte Speicherbereinigung, Leistung und funktionsfähiges Sandbox-Modell ich kenne. Die Entstehung vieler Sprachen zur Unterstützung der JVM ist wahrscheinlich weniger auf ihre "Vielseitigkeit" zurückzuführen, sondern vielmehr auf die Tatsache, dass der Java-Sprache einige wichtige Funktionen fehlen, die die Benutzer in einer Programmiersprache wünschen. Während die meisten Maschinensprachen nur etwa ein halbes Dutzend Datentypen haben (z. B. Byte, Halbwort, Wort, Doppelwort, Gleitkomma mit einfacher Genauigkeit und Gleitkomma mit doppelter Genauigkeit), lässt die überwiegende Mehrheit der Programmiersprachen die Verwendung von Code zu eine beliebige Anzahl von benutzerdefinierten Datentypen. Die JVM erkennt einige primitive Typen, die denen einer typischen Maschine ähneln, sowie einen weiteren Typ: die Promiscuous Object Reference. Die Java-Sprache erkennt ebenfalls diese Grundelemente, und Promiscuous Object Referenzen. Während eine Variable möglicherweise darauf beschränkt ist, keine Verweise auf Objekte zu speichern, die nicht zu einer bestimmten Klasse gehören, unterscheidet die Sprache nicht zwischen den folgenden Typen von TypfeldernList<String>das könnte von Instanz statt MyThingKlasse MyClass:

  • Ein Verweis auf etwas Code ist eine unveränderliche Implementierung von List<String>

  • Ein Verweis auf eine Instanz eines veränderlichen Listentyps, der niemals einem Objekt ausgesetzt wird, das ihn möglicherweise verändert.

  • Ein Verweis auf eine veränderbare Liste, auf die, außer während der Ausführung der MyThingsMethoden, möglicherweise nirgendwo im Universum ein anderer Verweis existieren könnte.

  • Ein Verweis auf eine veränderbare Liste, die einem anderen Objekt gehört , das dieses andere Objekt MyThingauf irgendeine Weise verwenden möchte .

  • Ein Verweis auf eine veränderbare Liste, die MyThingEigentümer ist, die aber auch anderen Objekten ausgesetzt wurde, damit sie etwas damit anfangen können.

Obwohl all diese Felder einen Typ haben könnten List<String>, enthalten sie sehr unterschiedliche Dinge. Eine expressive Sprache könnte eine Unterscheidung zwischen diesen Bedeutungen ermöglichen, Java jedoch nicht. Da eine Sprache solchen Dingen (zumindest außerhalb allgemeiner Kontexte) Bedeutung beimessen und auf der JVM ausgeführt werden kann, bleibt für JVM-Zielsprachen viel Raum, um Konzepte auszudrücken, die Java nicht ausdrücken kann.

Superkatze
quelle