# Architettura della macchina virtuale Java

L'architettura della macchina virtuale Java può essere così suddivisa:
* Un set di istruzioni per i bytecode
* Un gruppo di registri
* Uno stack
* Un'area di heap su cui opera la routine di garbage collection
* Un'area per la memorizzazione dei metodi

## La macchina virtuale Java

L'obiettivo della macchina virtuale di Java è quello di trovare un modo per scrivere e distribuire il software. Attualmente il mondo informatico è suddiviso da una parte in molteplici tipologie di linguaggi di programmazione e dall'altra dall'enorme sviluppo di internet che mette i programmatori di fronte al problema della condivisione del codice. Grazie alla sua flessibilità, alla sua semplicità e alla sua sicurezza, Java è utile per la programmazione in internet e ha assunto il ruolo di piattaforma centrale.

### Bytecode di Java

Il codice sorgente di Java viene compilato in bytecode e memorizzato in file con estensione .class. Per compilare tale codice viene fornito uno strumento che prende il nome di Javac. Questo strumento non viene considerato come un compilatore tradizionale proprio perché traduce il codice sorgente in bytecode. Il codice, a causa del formato, non può essere eseguito direttamente ma deve essere interpretato su ciascun computer. L'estrema portabilità e flessibilità del codice Java sono date, appunto, da questo passaggio intermedio.
Un'istruzione di bytecode è composta da un opcode di un byte, che serve per identificare l'istruzione in questione, e da zero o più operandi, ciascuno dei quali può essere più lungo di un byte. Quando gli operandi sono più lunghi di un byte, viene memorizzato per primo il big-endian (byte di ordine superiore), questi operandi vengono poi assemblati dal flusso di byte in fase di esecuzione. Ad esempio, un parametro a 16 bit viene rappresentato all'interno del flusso di istruzioni da due byte. Il set di istruzioni della macchina virtuale di Java interpreta i dati nelle aree di memoria di esecuzione come appartenenti a un insieme prefissato di tipi: i tipi primitivi, che sono rappresentati da diversi tipi interi con segno (byte, short, int, long), un tipo intero senza segno (char), due tipi in virgola mobile (float e double) e in più il tipo che fa riferimento a un oggetto (puntatore a 32 bit).

### Registri

I registri della macchina virtuale di Java sono affini ai registri che si trovano in un computer reale, essi contengono lo stato in cui si trova la macchina durante le operazioni, influiscono sul funzionamento di quest'ultima e vengono aggiornati dopo l'esecuzione di ciascun bytecode.
La macchina virtuale Java include i seguenti registri:
* pc - il program counter, indica il bytecode che sta per essere eseguito.
* vars - un puntatore alla prima variabile locale del metodo attualmente in esecuzione.
* frame - un puntatore all'ambiente di esecuzione del metodo corrente in esecuzione.
* optop - un puntatore al vertice dello stack degli operandi, è utilizzato per valutare tutte le espressioni aritmetiche.
L'ampiezza con cui Java definisce questi registri è di 32 bit. Essendo basata sullo stack, la macchina virtuale non fa alcun uso di registri per il passaggio o l'acquisizione di argomenti; ciò che ha portato i programmatori ad optare per questa scelta è stata la semplicità e la compattezza dei bytecode che favoriscono l'implementazione della macchina virtuale su architetture con pochi registri.

### Stack

Lo stack, che è alla base del funzionamento della macchina virtuale Java, viene utilizzato per passare i parametri alle istruzioni che vengono man mano eseguite e per ricevere i risultati da queste prodotti. Un frame dello stack di Java è affine a un frame dello stack di un convenzionale linguaggio di programmazione. Ogni frame contiene le informazioni associate ad una delle chiamate a metodo "impilate" sullo stack.
Ogni frame dello stack possiede tre aree (che potrebbero essere anche vuote):
* Le variabili locali per la chiamata al metodo
* L'ambiente di esecuzione del metodo stesso
* Lo stack degli operandi
Non si confonda lo stack delle chiamate a metodo con lo stack degli operandi. Quest'ultimo funziona in modo autonomo rispetto all'altro. L'unica correlazione che corre tra i due è che il secondo viene gestito in una area di memoria interna ai frames che sono presenti nel primo. Molto semplicisticamente, potremmo dire che abbiamo a che fare con uno stack nello stack.

### Area di heap

Con il termine heap si fa riferimento a quel sito della memoria nella quale vengono allocati gli oggetti appena creati. Al momento dell'avvio della JVM, una certa area di memoria (più ampia o ridotta a seconda dell'implementazione della macchina virtuale) viene spesso assegnata allo heap. Alcune implementazioni assegnano fin dall'avvio una ampia quantità di memoria allo heap, tenendo tale quantità costante per tutta l'esecuzione del programma; altre permettono a quest'area di espandersi fin dove concesso dall'ambiente di esecuzione (tra i fattori che influenzano questa quantità ci sono le impostazioni del sistema operativo e la disponibilità effettiva di memoria sulla macchina che sta eseguendo il programma). Il Garbage collector è deputato alla rimozione degli oggetti non più utilizzati dal programma man mano che questo è in esecuzione. Ciò consente ai programmatori di svincolarsi dal compito di liberare "manualmente" (inserendo apposite istruzioni nel codice sorgente) la memoria allocata per un oggetto quando quest'ultimo ha esaurito la sua funzione nel programma. Tale compito è addirittura obbligatorio in linguaggi come il C++. In effetti, il garbage collector è stato progettato proprio per evitare a run-time quegli errori che derivano dalla mancata deallocazione di memoria non più utilizzata o dal tentativo di deallocare memoria ancora in uso dal programma.

### Area di memorizzazione dei metodi

L'area di memorizzazione dei metodi contiene le tabelle dei simboli necessari per il link dinamico, informazioni di debug aggiuntive, ambienti di sviluppo da associare all'implementazione di qualsiasi metodo e i bytecode di Java che implementano tutti i metodi presenti nel sistema. Poiché i bytecode vengono memorizzati come flusso di byte, l'area dei metodi è allineata per byte mentre le altre aree sono allineate a parole di 32 bit.