Come funziona JVM: architettura JVM

Come funziona JVM: architettura JVM

Java Virtual Machine (JVM) è un componente principale di Java Runtime Environment (JRE) che consente ai programmi Java di essere eseguiti su qualsiasi piattaforma senza modifiche. JVM funge da interprete tra il bytecode Java e l'hardware sottostante fornendo la famosa funzionalità WORA (Write Once Run Anywhere) di Java.

  • Sorgente Java (.java) -> compilato da javac -> bytecode (.class)
  • JVM carica il bytecode, verifica che lo colleghi e quindi lo esegue
  • L'esecuzione può comportare l'interpretazione del bytecode o l'utilizzo della compilazione Just-In-Time (JIT) per convertire l'hot code in codice macchina nativo per le prestazioni
  • La Garbage Collection viene eseguita in background per recuperare memoria dagli oggetti inutilizzati

Architettura della JVM

L'immagine seguente mostra l'architettura e i componenti chiave di JVM.

Jvm

Componenti dell'architettura JVM

Ora discuteremo in dettaglio ogni componente della JVM.

1. Sottosistema caricatore di classi

È principalmente responsabile di tre attività. 

class_loader_subsystem

1. Caricamento

  • Legge i file .class e memorizza i metadati della classe nell'area dei metodi.
  • Crea un oggetto Class nell'heap che rappresenta la classe caricata.
Java
   class   GFG  {          static  {          System  .  out  .  println  (  'GFG class is loaded by the JVM!'  );      }      public     void     display  (){          System  .  out  .  println  (  'Method of GFG class is executed.'  );      }   }   public     class   Test  {      public     static     void     main  (  String  []     args  )     throws     Exception  {          System  .  out  .  println  (  'Main method started.'  );      // Loading the class explicitly using Class.forName()      Class  .  forName  (  'GFG'  );      System  .  out  .  println  (  'Class loaded successfully.'  );      // Creating object to execute method      GFG     obj     =     new     GFG  ();      obj  .  display  ();      }   }   

Produzione
Main method started. GFG class is loaded by the JVM! Class loaded successfully. Method of GFG class is executed.  

Nota: Per ogni carico .classe solo file uno viene creato l'oggetto della classe.

2. Collegamento: Responsabile della preparazione della classe caricata per l'esecuzione. Comprende tre passaggi:

  • Verifica: Garantisce che il bytecode segua le regole JVM e sia sicuro da eseguire.
  • Preparazione: Alloca memoria per variabili statiche e assegna valori predefiniti.
  • Risoluzione: Converte i riferimenti simbolici in riferimenti diretti in memoria.

3. Inizializzazione

  • Assegna valori effettivi a variabili statiche.
  • Esegue i blocchi statici definiti nella classe.

Tipi di caricatore di classi

  • Caricatore di classi Bootstrap: Carica le classi Java principali (JAVA_HOME/lib).
  • Caricatore di classi di estensione: Carica le classi dalla directory delle estensioni (JAVA_HOME/jre/lib/ext).
  • Caricatore classi di sistema/applicazione: Carica le classi dal percorso classi dell'applicazione.
Java
   // Java code to demonstrate Class Loader subsystem   public     class   Geeks      {      public     static     void     main  (  String  []     args  )      {      // String class is loaded by bootstrap loader and      // bootstrap loader is not Java object hence null      System  .  out  .  println  (  String  .  class  .  getClassLoader  ());      // Test class is loaded by Application loader      System  .  out  .  println  (  Geeks  .  class  .  getClassLoader  ());      }   }   

Produzione
null jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f  

2. Aree di memoria JVM

  • Area del metodo: Memorizza informazioni a livello di classe come nome della classe, metodi della classe genitore, variabili e dati statici. Condiviso attraverso la JVM.
  • Area dell'heap: Memorizza tutti gli oggetti. Condiviso attraverso la JVM.
  • Area della pila: Ogni thread ha il proprio stack di runtime; Il metodo Store chiama variabili locali negli stack frame. Distrutto quando il thread finisce.
  • Registri PC: Conserva l'indirizzo dell'istruzione attualmente in esecuzione per ciascun thread.
  • Stack di metodi nativi: Ogni thread ha uno stack separato per l'esecuzione del metodo nativo.

3. Motore di esecuzione 

Il motore di esecuzione esegue il file .class (bytecode). Legge il byte-code riga per riga, utilizza dati e informazioni presenti in varie aree di memoria ed esegue istruzioni. Può essere classificato in tre parti:

  • Interprete: Interpreta il bytecode riga per riga e quindi lo esegue. Lo svantaggio qui è che quando un metodo viene chiamato più volte ogni volta è richiesta l'interpretazione.
  • Compilatore Just-In-Time (JIT): Viene utilizzato per aumentare l'efficienza di un interprete. Compila l'intero bytecode e lo modifica in codice nativo, quindi ogni volta che l'interprete vede chiamate di metodo ripetute, JIT fornisce codice nativo diretto per quella parte, quindi non è necessaria la reinterpretazione, quindi l'efficienza viene migliorata.
  • Raccoglitore di rifiuti: Distrugge gli oggetti senza riferimenti. Per ulteriori informazioni su Garbage Collector fare riferimento Raccoglitore di rifiuti .

4. Interfaccia nativa Java (JNI)

È un'interfaccia che interagisce con le librerie di metodi nativi e fornisce le librerie native (C C++) necessarie per l'esecuzione. Consente alla JVM di chiamare librerie C/C++ e di essere chiamata da librerie C/C++ che potrebbero essere specifiche dell'hardware.

5. Librerie di metodi nativi

Si tratta di raccolte di librerie native necessarie per l'esecuzione di metodi nativi. Includono librerie scritte in linguaggi come C e C++.


Crea quiz