Cosa rende JVM così versatile da supportare così tante lingue JVM?


18

JVM supporta così tanti linguaggi diversi da Java come Groovy,Clojure,Scalaecc. Che sono linguaggi funzionali a differenza di Java (mi riferisco a Java prima della versione 8 dove Lambda'snon sono supportati) che non supporta le funzionalità funzionali. Su un livello elevato ciò che rende la JVM così versatile che può supportare sia linguaggi orientati agli oggetti che funzionali?


"Groovy, Clojure, Scala ecc. Che sono funzionali". Alcuni di questi sono più funzionali di altri. Userei una scala con Groovy il meno funzionale e Clojure di più, con Scala al centro.
Vorg van Geir,

Risposte:


37

Rispetto ad altre VM, la JVM in realtà non è particolarmente versatile . Supporta direttamente OO tipicamente. Per tutto il resto, devi vedere quali parti puoi usare e come puoi costruire tutto il resto della tua lingua su quelle parti.

Ad esempio, fino a quando Java 7 non ha introdotto il invokedynamicbytecode, è stato molto difficile implementare un linguaggio OO tipizzato in modo dinamico sulla JVM: è stato necessario utilizzare soluzioni alternative complesse che erano dannose per le prestazioni e provocavano tracce di stack orribilmente gonfiate.

Eppure, un sacco di linguaggi dinamici (Groovy, Jython, JRuby tra gli altri) sono stati implementati sulla JVM prima di quello.

Non perché JVM sia così versatile, ma perché è così diffuso e perché ha implementazioni molto mature, ben supportate e ad alte prestazioni.

E, forse ancora più importante, perché c'è un'enorme quantità di codice Java là fuori che fa praticamente qualsiasi cosa, e se la tua lingua viene eseguita sulla JVM, puoi facilmente offrire servizi per integrarti con quel codice. Fondamentalmente, far funzionare la tua lingua su JVM è la versione del 21 ° secolo che offre l'interoperabilità con C.


Buona risposta (+1). L'ultimo punto che menzioni è che IMHO è anche responsabile della popolarità di Java come lingua: alla fine, avere un'enorme quantità di codice che puoi riutilizzare gratuitamente può farti risparmiare molto più tempo di poter usare il linguaggio più recente e alla moda Caratteristiche.
Giorgio,

4

La JVM è stata scritta per agire sostanzialmente come una CPU, c'è una serie di istruzioni, un po 'come un assembly, che la VM esegue chiamati bytecode. Se riesci a scrivere un compilatore che genera un set valido di bytecode, JVM può eseguirli.

Wikipedia ha un elenco dei bytecode:

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

così come una spiegazione di come la JVM carica i codici byte:

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

Utilizzando i bytecode di stile invoke, un linguaggio funzionale può eseguire il codice, indipendentemente dall'aspetto della sorgente. Inoltre, con l'aggiunta di invokevirtual, le implementazioni del linguaggio come jruby hanno dato una certa flessibilità al modo in cui funzionano.


1
La stessa cosa vale per ogni altra VM in circolazione: la YARV Ruby VM, la Rubinius Ruby VM, la CPython VM (che dopo tutto precede la JVM), Parrot, varie Smalltalk e Lisp VM, e ovviamente la Pascal P- Sistema di codice, dopo il quale viene modellata la JVM.
Jörg W Mittag,

D'accordo, la JVM non è sicuramente la prima VM in circolazione. Penso che JVM sia popolare per altre lingue perché Java è popolare, la VM è attivamente sviluppata e ben documentata.
Sasbury,

2

Aggiungerò che JVM supporta un modello di memoria ( JMM ) ben definito e abbastanza decente, il che significa un buon supporto per un comportamento di threading coerente (anche se di basso livello). Ha anche un potente compilatore Just In Time (non più utile per i linguaggi dinamici grazie a MethodHandles e invokedynamic).

Ultimo ma non meno importante è il sottosistema Garbage Collection di JVM che (con la giusta regolazione) gestisce la memoria per te indipendentemente dalla lingua in cima.


Il JMM è una delle mie cose meno preferite di Java. Sono un fan di dati effettivamente immutabili (ad es. Array il cui contenuto non cambierà mai dopo che sono visibili ad altri thread), ma ho dato una dichiarazione come someField = new int[]{42};gli unici modi per garantire che qualsiasi thread che vede il nuovo array vedrà il valore 42 devono fare il campo finalo volatile. Se il campo viene generato pigramente ma vi si accede frequentemente, farlo finalnon funzionerà e farlo volatileimporre una penalità di sincronizzazione inutile ogni volta che si accede. Anche nel modello .NET più
lento

... il codice potrebbe richiedere che la popolazione dell'array si verifichi prima dell'archivio del riferimento. Altri thread che leggono il campo potrebbero o meno vedere il riferimento al nuovo array, ma non avrebbero alcun costo per se stessi che se vedono il nuovo array ne vedranno il contenuto.
supercat

1

L'elemento chiave in questo è la separazione della compilation dalla fase di esecuzione. Con questo è possibile scrivere altri compilatori compilando altre lingue in bytecode.

Il bytecode agisce in modo simile al codice macchina di una CPU - hai tutte le piccole operazioni necessarie per eseguire un programma - puoi ottenere una variabile, fare matematica su di essa, eseguire operazioni condizionali ecc.

Anche Java non è speciale. In Java l'esistenza di più lingue non era nemmeno un obiettivo di progettazione, a differenza di altre macchine virtuali. Per Microsoft .Net CIL la capacità di eseguire più lingue (C #, VB.Net, ...) è stata un elemento chiave di progettazione, anche ParrotVM del progetto Perl6 mirava a essere una macchina virtuale generica.

Per il gusto di farlo, ho creato una volta la prova che anche il motore Zend di PHP lo avrebbe permesso.

E francamente non è una novità, anche su hardware reale è possibile eseguire più lingue, ad esempio C o Fortran.

La differenza rispetto a questa separazione dalla compilazione e dall'esecuzione sono gli interpreti clssic, come alcune forme di Basic, script di shell, ecc. Spesso funzionano in modo da eseguire il codice più o meno in una riga per riga senza portarlo in una forma immediata nel mezzo.


1

JVM è la prima macchina virtuale di cui sono a conoscenza che combina garbage collection, prestazioni e un modello sandbox praticabile. L'emergere di molti linguaggi a supporto della JVM probabilmente non è tanto un risultato della sua "versatilità", quanto piuttosto il fatto che il linguaggio Java manchi di alcune caratteristiche significative che le persone desiderano in un linguaggio di programmazione. Ad esempio, mentre la maggior parte dei linguaggi di macchine ha solo una mezza dozzina di tipi di dati (ad esempio byte, mezza parola, parola, doppia parola, virgola mobile a precisione singola e virgola mobile a precisione doppia), la stragrande maggioranza dei linguaggi di programmazione consente l'utilizzo del codice un numero arbitrario di tipi di dati definiti dall'utente. La JVM riconosce alcuni tipi primitivi simili a quelli su una macchina tipica, oltre a un altro tipo: il Promiscuous Object Reference. Anche il linguaggio Java riconosce quei primitivi, e riferimenti a oggetti promiscui. Mentre una variabile può essere costretta a non contenere riferimenti a qualcosa che non è una classe particolare, il linguaggio non fa distinzioni tra i seguenti tipi di campo di tipoList<String>che potrebbe essere tenuto dalla MyThingclasse di istanza MyClass:

  • Un riferimento a qualcosa di codice sa essere un'implementazione immutabile di List<String>

  • Un riferimento a un'istanza di un tipo di elenco mutabile che non sarà mai esposto a qualcosa che potrebbe mutarlo.

  • Un riferimento a un elenco mutabile a cui, salvo durante l'esecuzione dei MyThingsmetodi di, nessun altro riferimento potrebbe eventualmente esistere in qualsiasi parte dell'universo.

  • Un riferimento a un elenco mutabile che appartiene a qualche altro oggetto , che quell'altro oggetto vorrebbe MyThingusare in qualche modo.

  • Un riferimento a un elenco mutabile che MyThingpossiede, ma che ha anche esposto ad alcuni altri oggetti in modo che possano farci qualcosa.

Sebbene tutti questi campi possano avere tipo List<String>, contengono cose molto diverse. Un linguaggio espressivo potrebbe consentire una distinzione tra questi significati, ma Java no. Poiché una lingua potrebbe associare un significato a tali cose (almeno al di fuori di contesti generici) ed essere eseguita su JVM, ciò lascia molto spazio ai linguaggi con targeting JVM per esprimere concetti che Java non può.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.