3. L'ARCHITETTURA DELLA JAVA VIRTUAL MACHINE

Nella specifica della Java virtual machine, l’aspetto di una istanza della virtual machine è descritta in termini di : sottosistema, aree di memoria, tipi di dati, ed istruzioni.

Queste componenti descrivono un’architettura per la JVM astratta.


      

La Figura 3-1. mostra un diagramma a blocchi della java virtual machine che include i principali sottosistemi e aree di memoria descritte nella specifica.

Ogni Virtual Machine Java ha il sottosistema class loader che è il meccanismo per caricare tipi (classi ed interfacce) dati i nomi completi.

Ogni Java virtual machine ha anche un execution engine: un meccanismo responsabile dell’esecuzione delle istruzioni contenute nei metodi delle classi caricate.

 

Quando una JVM esegue un programma, necessita di memoria per memorizzare, tra l’altro i bytecodes ed altre informazioni che estrae dai class files caricati, oggetti che il programma istanzia, parametri per i metodi, valori di ritorno, variabili locali, e risultati intermedi della computazione. La JVM organizza la memoria di cui necessita per eseguire un programma in diverse aree dati di runtime.

La natura astratta della specifica dell’area di runtime rende più semplice implementare la virtual machine su una vasta varietà di computers. Alcune aree di runtime sono condivise tra tutte le threads di un’applicazione, altre sono individuali.

Ogni istanza della JVM ha un’Area metodo e uno Heap.

 

Queste aree sono condivise da tutte le threads in esecuzione sulla virtual machine.

Quando la virtual machine carica un class file:

  1. elabora le informazioni sul tipo dai dati binari contenuti nel class file
  2. pone questo tipo di informazione nell’area metodo.

Come il programma viene eseguito, la virtual machine pone tutti gli oggetti che il programma istanzia sullo heap.

 

 

Implementazioni differenti di virtual machine possono avere differenti vincoli di memoria: molta memoria in cui lavorare o molto poca, usare la memoria virtuale oppure no.

                              

 Figura 3-2. Aree di Run-time condivise da tutte le thread

 

Appena una nuova thread è creata, essa ottiene il proprio registro program counter (pc) e stack.

Se la thread sta eseguendo un metodo di Java (non nativo), il valore del registro pc indica la prossima istruzione da eseguire.

Una thread dello stack Java memorizza lo stato dell’invocazione del metodo di Java (non nativo) definendo:

  1. le sue variabili locali,
  2. i parametri con cui è stato invocato,
  3. i valori di ritorno (se ce ne sono),
  4. calcoli intermedi.

 

Lo stato dell’invocazione dei metodi nativi è memorizzato nei rispettivi stacks dipendenti dall’implementazione, ad esempio in registri o altre aree di memoria implementazione dipendenti.

 

Quando una thread invoca un metodo, la JVM immette un nuovo frame sullo stack della thread e quando il metodo termina, la virtual machine preleva e scarta il frame per quel metodo.

 

La JVM non ha registri per memorizzare i valori intermedi. Il set di istruzioni usa lo stack di Java per memorizzare i valori dei dati intermedi. Questo approccio è stato mantenuto dai progettisti di Java per mantenere compatto il set di istruzioni della JVM e facilitare l’implementazione con pochi ed irregolari registri ad utilizzo generale. Inoltre, l’architettura basata su stack del set di istruzioni della JVM facilita il compito di ottimizzazione del codice da parte di compilatori dinamici che operano a run time in qualche implementazione della virtual machine.

 

La figura 3-3 illustra le aree di memoria che la JVM crea per ogni thread. Queste aree sono di proprietà della thread e nessuna thread può accedere al registro pc o allo stack di un'altra thread.

 

      

                         Figura 3-3. Aree dati di Runtime esclusive per ogni thread

 

La Figura 3-3 mostra uno spaccato di esecuzione di una istanza di virtual machine in cui tre thread sono in esecuzione. All'istante fotografato, le prime due thread stanno eseguendo metodi Java, la terza thread  sta eseguendo un metodo nativo.

Il top dello stack è mostrato sul fondo della figura. I frame dello stack per i metodi correntemente in esecuzione sono in grigio chiaro. Per le thread che stanno correntemente eseguendo un metodo Java, il registro pc indica la prossima istruzione da eseguire. Poiché la terza thread sta eseguendo un metodo nativo, il contenuto del suo registro pc è --mostrato in grigio scuro-- indefinito.