Domanda

Come una sorta di seguito alla domanda chiamata Differenze tra bytecode MSIL e Java?, quali sono le (principali) differenze o somiglianze nel modo in cui funziona la Java Virtual Machine rispetto a come funziona la Java Virtual Machine .NET Framework Common Language Runtime (CLR) funziona?

Inoltre, è il struttura .NET CLR è una "macchina virtuale" o non ha gli attributi di una macchina virtuale?

È stato utile?

Soluzione

Ci sono molte somiglianze tra entrambe le implementazioni (e secondo me:sì, sono entrambe "macchine virtuali").

Per prima cosa, sono entrambe VM basate su stack, senza la nozione di "registri" come siamo abituati a vedere in una CPU moderna come x86 o PowerPC.La valutazione di tutte le espressioni ((1 + 1) / 2) viene eseguita inserendo gli operandi nello "stack" e quindi estraendo tali operandi dallo stack ogni volta che un'istruzione (addizione, divisione, ecc.) deve consumare tali operandi.Ogni istruzione rimette i suoi risultati nello stack.

È un modo conveniente per implementare una macchina virtuale, perché praticamente ogni CPU al mondo ha uno stack, ma il numero di registri è spesso diverso (e alcuni registri hanno scopi speciali e ogni istruzione prevede i suoi operandi in registri diversi, ecc. ).

Quindi, se hai intenzione di modellare una macchina astratta, un modello basato esclusivamente sullo stack è un buon modo per procedere.

Naturalmente le macchine reali non funzionano in questo modo.Quindi il compilatore JIT è responsabile dell'esecuzione della "registrazione" delle operazioni del bytecode, essenzialmente pianificando i registri effettivi della CPU in modo che contengano operandi e risultati quando possibile.

Quindi, penso che sia uno dei maggiori punti in comune tra CLR e JVM.

Per quanto riguarda le differenze...

Una differenza interessante tra le due implementazioni è che CLR include istruzioni per creare tipi generici e quindi per applicare specializzazioni parametriche a tali tipi.Pertanto, in fase di esecuzione, CLR considera un List<int> come un tipo completamente diverso da un List<String>.

Dietro le quinte, utilizza lo stesso MSIL per tutte le specializzazioni del tipo di riferimento (quindi un List<String> utilizza la stessa implementazione di un List<Object>, con diversi tipi di cast ai limiti dell'API), ma ogni tipo di valore utilizza la sua implementazione unica (List<int> genera codice completamente diverso da List<double>).

In Java, i tipi generici sono puramente un trucco del compilatore.La JVM non ha idea di quali classi abbiano argomenti di tipo e non è in grado di eseguire specializzazioni parametriche in fase di runtime.

Da un punto di vista pratico, ciò significa che non è possibile sovraccaricare i metodi Java su tipi generici.Non è possibile avere due metodi diversi, con lo stesso nome, che differiscono solo se accettano un List<String> o un List<Date>.Naturalmente, poiché CLR conosce i tipi parametrici, non ha problemi a gestire metodi sovraccarichi di specializzazioni di tipo generico.

Su base quotidiana, questa è la differenza che noto di più tra CLR e JVM.

Altre differenze importanti includono:

  • Il CLR presenta chiusure (implementate come delegati C#).La JVM supporta le chiusure solo a partire da Java 8.

  • Il CLR ha coroutine (implementate con la parola chiave C# 'yield').La JVM no.

  • Il CLR consente al codice utente di definire nuovi tipi di valore (strutture), mentre la JVM fornisce una raccolta fissa di tipi di valore (byte, short, int, long, float, double, char, boolean) e consente solo agli utenti di definire nuovi tipi di riferimento tipi (classi).

  • Il CLR fornisce il supporto per dichiarare e manipolare i puntatori.Ciò è particolarmente interessante perché sia ​​JVM che CLR utilizzano implementazioni di garbage collector di compattazione generazionale rigorose come strategia di gestione della memoria.In circostanze normali, un GC a compattazione rigorosa ha davvero difficoltà con i puntatori, perché quando si sposta un valore da una posizione di memoria a un'altra, tutti i puntatori (e i puntatori a puntatori) diventano non validi.Ma CLR fornisce un meccanismo di "blocco" in modo che gli sviluppatori possano dichiarare un blocco di codice all'interno del quale CLR non può spostare determinati puntatori.È molto conveniente.

  • L'unità di codice più grande nella JVM è un "pacchetto", come evidenziato dalla parola chiave "protetto", o probabilmente un JAR (ad es.Java ARchive) come evidenziato dalla possibilità di specificare un jar nel classpath e trattarlo come una cartella di codice.In CLR, le classi vengono aggregate in "assembly" e CLR fornisce la logica per ragionare e manipolare gli assembly (che vengono caricati in "AppDomains", fornendo sandbox a livello di applicazione secondaria per l'allocazione della memoria e l'esecuzione del codice).

  • Il formato bytecode CLR (composto da istruzioni e metadati MSIL) ha meno tipi di istruzioni rispetto alla JVM.Nella JVM, ogni operazione univoca (aggiungere due valori int, aggiungere due valori float, ecc.) ha la propria istruzione univoca.Nel CLR, tutte le istruzioni MSIL sono polimorfiche (aggiungi due valori) e il compilatore JIT è responsabile della determinazione dei tipi degli operandi e della creazione del codice macchina appropriato.Non so quale sia la strategia preferibile, però.Entrambi hanno dei compromessi.Il compilatore JIT HotSpot, per la JVM, può utilizzare un meccanismo di generazione del codice più semplice (non ha bisogno di determinare i tipi di operandi, perché sono già codificati nell'istruzione), ma ciò significa che necessita di un formato bytecode più complesso, con più tipi di istruzioni.

Utilizzo Java (e ammiro la JVM) da circa dieci anni ormai.

Ma, a mio parere, CLR è ora l’implementazione migliore, in quasi ogni aspetto.

Altri suggerimenti

La tua prima domanda è quella di confrontare la JVM con .NET Framework - suppongo che tu abbia effettivamente voluto confrontare con il CLR. In tal caso, penso che potresti scrivere un piccolo libro su questo ( EDIT: sembra che Benji abbia già :-)

Una differenza importante è che CLR è progettato per essere un'architettura indipendente dal linguaggio, a differenza della JVM.

Un'altra importante differenza è che il CLR è stato specificamente progettato per consentire un alto livello di interoperabilità con il codice nativo. Ciò significa che il CLR deve gestire l'affidabilità e la sicurezza quando si accede e modifica la memoria nativa e anche gestisci il marshalling tra le strutture di dati basate su CLR e le strutture di dati native.

Per rispondere alla tua seconda domanda, il termine & # 8220; macchina virtuale & # 8221; è un termine più antico dal mondo dell'hardware (ad es. virtualizzazione della 360 di IBM negli anni '60) che significava un'emulazione software / hardware della macchina sottostante per realizzare lo stesso tipo di cose che fa VMWare.

Il CLR viene spesso indicato come " motore di esecuzione " ;. In questo contesto, questa è un'implementazione di una macchina IL sopra un x86. Questo è anche ciò che fa la JVM, sebbene si possa sostenere che esiste una differenza importante tra i bytecode polimorfici del CLR e i bytecode tipizzati della JVM.

Quindi la risposta pedante alla tua seconda domanda è " no " ;. Ma dipende davvero da come definisci questi due termini.

EDIT: Un'altra differenza tra JVM e CLR è che JVM (versione 6) è molto riluttante a rilasciare la memoria allocata al sistema operativo, anche dove è possibile.

Ad esempio, supponiamo che un processo JVM venga avviato e alloca inizialmente 25 MB di memoria dal sistema operativo. Il codice dell'app tenta quindi di assegnare allocazioni che richiedono altri 50 MB. La JVM assegnerà altri 50 MB dal sistema operativo. Una volta che il codice dell'applicazione ha smesso di usare quella memoria, viene raccolto in modo inutile e la dimensione dell'heap JVM diminuirà. Tuttavia, la JVM libererà la memoria del sistema operativo allocata solo in determinate circostanze molto specifiche . Altrimenti, per il resto della durata del processo quella memoria rimarrà allocata.

Il CLR, invece, rilascia la memoria allocata al sistema operativo se non è più necessario. Nell'esempio sopra, il CLR avrebbe rilasciato la memoria una volta che l'heap fosse diminuito.

Ulteriori dettagli sulle differenze sono disponibili presso varie fonti accademiche e private. Un buon esempio è CLR Design Choices .

Alcuni esempi specifici includono:

  • Alcuni opperand di basso livello sono digitati come " aggiungi due ints " dove come CLR utilizza un operando polimorfico. (es. fadd / iadd / ladd vs basta aggiungere)
  • Attualmente, la JVM esegue una profilazione e un'ottimizzazione del runtime più aggressive (ad es. Hotspot). CLR attualmente esegue le ottimizzazioni JIT, ma non l'ottimizzazione del runtime (ovvero sostituisci il codice mentre sei in esecuzione).
  • CLR non incorpora metodi virtuali, JVM fa ...
  • Supporto per tipi di valore nel CLR oltre al " primitives " ;.

CLR e JVM sono entrambe macchine virtuali.

.NET Framework e Java Runtime Environment sono il raggruppamento delle rispettive VM e delle loro librerie. Senza librerie, le VM sono piuttosto inutili.

Non è una macchina virtuale, il framework .net compila gli assembly in binario nativo al momento della prima esecuzione:

Nell'informatica, la compilazione just-in-time (JIT), nota anche come traduzione dinamica, è una tecnica per migliorare le prestazioni di runtime di un programma per computer. JIT si basa su due idee precedenti in ambienti di runtime: compilazione bytecode e compilazione dinamica. Converte il codice in fase di esecuzione prima di eseguirlo in modo nativo, ad esempio bytecode in codice macchina nativo. Il miglioramento delle prestazioni rispetto agli interpreti deriva dalla memorizzazione nella cache dei risultati della traduzione di blocchi di codice e non dalla semplice rivalutazione di ogni riga o operando ogni volta che viene soddisfatta (vedere Lingua interpretata). Presenta inoltre vantaggi rispetto alla compilazione statica del codice in fase di sviluppo, in quanto può ricompilare il codice se viene ritenuto vantaggioso e può far valere le garanzie di sicurezza. In questo modo JIT può combinare alcuni dei vantaggi dell'interpretazione e della compilazione statica (anticipata).

Diversi ambienti di runtime moderni, come Microsoft .NET Framework, la maggior parte delle implementazioni di Java e, più recentemente, Actionscript 3, si basano sulla compilazione JIT per l'esecuzione di codice ad alta velocità.

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

L'aggiunta di .NET framework contiene una macchina virtuale, proprio come Java.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top