Heap vs stack vs Metaspace: come funziona la JVM

  • Di
  • 2025-05-15 - 5 minuti
banner

La gestione della memoria di Java svolge un ruolo importante nell’eseguire in maniera efficiente le applicazioni Java.

Capirlo fino in fondo può aiutare chi sviluppa a evitare colli di bottiglia nelle prestazioni e in memory leak. Questo post ti introdurrà ai tre componenti principali del modello di memoria di Java: Heap, Stack e Metaspace.

Cosa vedrai

Heap

L’heap è un componente critico del modello di memoria di Java, perché funge da area primaria per l’archiviazione di oggetti Java.

Ogni volta che un oggetto viene creato utilizzando la parola chiave new in Java, la memoria per quell’oggetto viene allocata dall’heap. È qui che opera anche il Garbage Collector, che recupera la memoria utilizzata dagli oggetti che non sono più necessari, il che aiuta a prevenire memory leaks e un utilizzo eccessivo della memoria.

Struttura dell’heap

L’heap Java è suddiviso in due aree principali:

  • Young Generation: è qui che vengono allocati tutti i nuovi oggetti. La Young Generation è ulteriormente divisa in uno spazio “Eden” e due spazi “Survivor”. Gli oggetti risiedono inizialmente in Eden e si spostano in uno spazio Survivor se rimangono in vita dopo un evento di “pulizia” da parte del Garbage Collector.

  • Old Generation: conosciuta anche come tenerured generation, riguarda gli oggetti che sono sopravvissuti a diversi cicli di garbage collection nella fase “young” e che vengono promossi in questo spazio, che è progettato per oggetti con un ciclo di vita più lungo. La soglia di sopravvivenza è impostata tramite le policy del garbage collector e può essere regolata da chi sviluppa.

  • Con Java 8 e versioni successive, l’introduzione di Metaspace ha sostituito Permanent Generation.

Esempio

public class HeapExample {
    public static void main(String[] args) {
        Customer customer = new Customer("John Doe");
        System.out.println(customer.getName());
    }
}

class Customer {
    private String name;
    
    public Customer(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Nell’esempio precedente, l’oggetto Customer, incluso il suo attributo name, questo viene allocato nell’heap. La capacità dell’heap di allocare dinamicamente la memoria lo rende ideale per la gestione di oggetti complessi con durate di vita variabili.

Stack

Ogni thread in un’applicazione Java ha il suo stack, che viene utilizzato per memorizzare variabili di breve durata e informazioni sulle chiamate di metodo.

Lo stack è di dimensioni inferiori rispetto all’heap, ma è fondamentale per gestire le chiamate ai metodi e memorizzare variabili locali oppure i risultati intermedi delle espressioni.

Come funziona lo Stack

Quando viene invocato un nuovo metodo, sullo stack viene creato un nuovo blocco chiamato “stack frame”. Questo stack frame contiene tutte le variabili locali, i parametri e l’indirizzo di ritorno del metodo. Una volta che il metodo completa l’esecuzione, il suo stack frame viene scartato, rendendo quest’area altamente efficiente nella gestione della memoria che è necessaria solo durante una chiamata al metodo.

Esempio

public class StackExample {
    public static void main(String[] args) {
        int result = add(5, 10);
        System.out.println("Result: " + result);
    }

    public static int add(int a, int b) {
        int sum = a + b;
        return sum; // The local variables 'a', 'b', and 'sum' are stored in the stack frame for the add method.
    }
}

Questo esempio dimostra come lo stack viene utilizzato per gestire il flusso di esecuzione del metodo e il ciclo di vita delle variabili locali.

Metaspace

Metaspace è un’area di memoria non-heap che è nata con Java 8, in sostituzione di Permanent Generation. È utilizzata per archiviare metadati come definizioni di classe, metodi e campi.

A differenza dell’heap, Metaspace è allocato fuori dalla memoria nativa e la sua dimensione non è fissa ma può aumentare dinamicamente, il che aiuta a prevenire gli errori di tipo OutOfMemoryError.

Monitoraggio e gestione del Metaspace

Poiché Metaspace può crescere dinamicamente, monitorarne le dimensioni e l’utilizzo è fondamentale per evitare che la memoria di sistema si esaurisca. Java fornisce diverse opzioni per monitorare e gestire le dimensioni di Metaspace, come -XX:MetaspaceSize e -XX:MaxMetaspaceSize, che consentono a chi sviluppa di impostare rispettivamente le dimensioni iniziali e massime di Metaspace.

Importanza del Metaspace

La sua introduzione migliora le prestazioni e la scalabilità regolando dinamicamente l’utilizzo della memoria in base alle richieste dell’applicazione, consentendo così alle applicazioni Java di gestire i metadati delle classi in modo più efficiente. Ciò è particolarmente utile in ambienti in cui molte classi vengono caricate e scaricate.

Schema della gestione degli spazi della JVM

Memoria nativa

Nello schema riportato sopra, viene mostrato un macro-gruppo chiamato memoria nativa: si tratta di un’area di memoria esterna al “normale” heap, ma in genere è una parte della memoria totale risparmiata dal sistema operativo per il processo JVM. Parte della memoria nativa è assegnata all’heap C, ossia lo spazio utilizzato dai programmi C nativi nei programmi Java, e parte allo stack.

Conclusione

Comprendere il modello di memoria di Java è fondamentale per ottimizzare le prestazioni delle applicazioni ed evitare problemi correlati alla memoria. Imparando a conoscere heap, stack e metaspace, puoi prendere decisioni più consapevoli quando sviluppi applicazioni Java. Monitora sempre l’utilizzo della memoria per assicurarti che le tue applicazioni funzionino in modo efficiente e per rilevare potenziali perdite di memoria!

Post correlati

TheRedCode.it - Il mondo #tech a piccoli #bit

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome
Logo de La Locanda del Tech
Logo di Tomorrow Devs
Logo di Coderful
Logo di DevDojo

Non perderti gli ultimi aggiornamenti, iscriviti a TheRedCode Digest!

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

Vuoi diventare #tech content creator? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!