Gestione della memoria in Java
โก Riepilogo intelligente
Gestione della memoria in Java spiega come la JVM divide la memoria di runtime tra Stack, Heap, Codee le regioni statiche, il modo in cui i riferimenti agli oggetti fluiscono durante le chiamate ai metodi e come il Garbage Collector recupera gli oggetti irraggiungibili in modo che le applicazioni rimangano stabili e prive di perdite di memoria.

Cos'รจ la memoria stack in Java?
Memoria dello stack in Java Lo Stack รจ la regione di memoria della JVM che memorizza i frame dei metodi, le variabili locali e le variabili di riferimento per ogni thread. Lo Stack viene sempre acceduto secondo l'ordine Last-In-First-Out (LIFO), quindi il metodo invocato piรน di recente si trova in cima e le sue variabili locali vengono inserite e rimosse insieme al frame.
Ogni filo nel Java La macchina virtuale riceve il proprio Stack, che per impostazione predefinita mantiene le invocazioni dei metodi isolate e thread-safe. I tipi primitivi come int, boolean e double risiedono direttamente all'interno del frame, mentre i riferimenti agli oggetti memorizzati nello Stack puntano agli oggetti allocati nell'Heap.
Che cos'รจ la memoria Heap in Java?
La memoria heap รจ la regione JVM condivisa che contiene ogni Java Oggetto e array creati con l'operatore new, insieme a tutte le variabili di riferimento che appartengono a tali oggetti come campi di istanza. A differenza dello Stack, l'Heap รจ condiviso tra tutti i thread, motivo per cui l'accesso agli oggetti spesso richiede la sincronizzazione.
L'heap รจ l'area gestita dal Garbage Collector. Le moderne JVM HotSpot dividono l'heap in una Young Generation per gli oggetti di breve durata e una Old Generation per gli oggetti di lunga durata, con i metadati delle classi memorizzati in una regione nativa separata chiamata Metaspace.
Allocazione memoria in Java
Allocazione memoria in Java ร il processo mediante il quale la JVM riserva regioni di memoria virtuale per variabili e istanze di classi e strutture durante l'esecuzione del programma. La memoria non viene allocata a un oggetto al momento della dichiarazione; viene creato solo un riferimento. L'effettiva allocazione dell'oggetto avviene tramite l'operatore `new`, quindi ogni oggetto risiede nell'heap.
Migliori Java L'allocazione della memoria รจ suddivisa nelle seguenti sezioni:
- Heap
- pila
- Code
- statica
Questa suddivisione della memoria รจ necessaria per una gestione efficace del tempo di esecuzione.
- Migliori Code la sezione contiene il tuo compilato codice a byte.
- Migliori pila reparto Negozio metodi, variabili locali e variabili di riferimento.
- Migliori Heap sezione contiene oggetti e possono anche contenere variabili di riferimento memorizzate come campi di istanza.
- Migliori statica la sezione contiene dati statici e metodi statici condiviso tra tutte le istanze.
Differenza tra variabile locale e di istanza
Capire dove risiede ogni tipo di variabile nella JVM aiuta a spiegare il comportamento di Stack e Heap. variabile di istanza รจ dichiarato all'interno di una classe ma al di fuori di qualsiasi metodoe risiede nell'Heap come parte del suo oggetto.
class Student{ int num; // num is instance variable public void showData{}
A variabile locale รจ dichiarato all'interno di un metodo, inclusi gli argomenti del metodoe risiede nello Stack all'interno del frame attivo.
public void sum(int a){ int x = a + 3; // a, x are local variables }
Differenza tra Stack e Heap
Lo Stack e l'Heap risolvono problemi diversi all'interno della JVM. Lo Stack fornisce a ciascun thread un'allocazione rapida e deterministica per i dati di breve durata legati all'ambito del metodo, mentre l'Heap offre una regione condivisa per gli oggetti di lunga durata a cui qualsiasi thread puรฒ fare riferimento. Il breve video qui sotto riassume le differenze prima della spiegazione dettagliata che segue.
Clicchi Qui. se il video non รจ accessibile
Per capire come Stack e Heap collaborano, consideriamo un metodo main che chiama il metodo m1.
public void m1{ int x = 20; }
Nello stack della JVM viene creato un frame per il metodo m1.
La variabile x in m1 viene creata anche nel frame per m1 sullo Stack, come mostrato nell'immagine sottostante.
Il metodo m1 chiama quindi il metodo m2. Nello stack, viene creato un nuovo frame per m2 sopra il frame per m1.
Le variabili locali b e c vengono create anche all'interno del frame per m2 sullo Stack.
public void m2(int b){ boolean c; }
Successivamente, m2 chiama il metodo m3. Anche in questo caso, viene creato un frame per m3 in cima allo Stack, come mostrato di seguito.
Ora diciamo che il metodo m3 crea un oggetto per la classe Account, che ha due variabili di istanza int p e int q.
class Account { int p; int q; }
Ecco il codice per il metodo m3.
public void m3(){ Account ref = new Account(); // more code }
L'istruzione new Account() crea un oggetto Account nell'heap.
La variabile di riferimento ref viene creata sullo Stack all'interno del frame per m3.
L'operatore di assegnazione fa sรฌ che la variabile di riferimento punti all'oggetto sull'heap.
Una volta completata l'esecuzione del metodo, il controllo ritorna al metodo chiamante, che in questo caso รจ il metodo m2.
Il frame per il metodo m3 viene svuotato dallo stack.
Poichรฉ la variabile di riferimento non punta piรน all'oggetto nell'heap, tale oggetto diventa idoneo per la raccolta dei rifiuti (garbage collection).
Una volta terminato il metodo m2, questo viene rimosso dallo stack e tutte le sue variabili diventano non disponibili. Lo stesso accade per il metodo m1, e infine il controllo ritorna al metodo main.
Cosa succede se un oggetto contiene un altro riferimento come variabile di istanza?
public static void main(String args[]) { A parent = new A(); // more code } class A { B child = new B(); int e; } class B { int c; int d; }
In questo caso, la variabile di riferimento child risiede nell'heap come parte dell'oggetto A e, a sua volta, punta al proprio oggetto B, come mostrato di seguito.
In cosa consiste la Garbage Collection Java?
Raccolta rifiuti a Java Il Garbage Collector รจ il processo tramite il quale la JVM gestisce automaticamente la memoria. Il Garbage Collector individua gli oggetti che non sono piรน raggiungibili da alcun riferimento attivo e ne recupera la memoria. L'allocazione dinamica della memoria avviene tramite l'operatore `new` e la memoria rimane allocata finchรฉ il programma non detiene piรน alcun riferimento all'oggetto.
Quando non rimangono riferimenti, l'oggetto viene considerato non piรน necessario e la memoria che occupa puรฒ essere recuperata. Non c'รจ bisogno esplicito di distruggere un oggetto perchรฉ Java gestisce automaticamente la deallocazione tramite il Garbage Collector.
La tecnica alla base di questo รจ nota come Raccolta dei rifiutiI programmi che non riescono a rilasciare la memoria finiscono per bloccarsi quando non rimane piรน nulla da allocare. Si dice che tali programmi abbiano perdite di memoria. Raccolta rifiuti a Java si avvia automaticamente per tutta la durata del programma, il che elimina l'onere della deallocazione manuale e riduce il rischio di fughe di dati.
In C, al contrario, il programmatore รจ responsabile del rilascio della memoria allocata dinamicamente tramite la funzione free(). ร qui che Java La gestione della memoria offre un notevole vantaggio.
Le moderne JVM HotSpot includono diversi Garbage Collector ottimizzati per diversi carichi di lavoro. Il Garbage Collector G1 predefinito punta a un throughput bilanciato e a tempi di pausa su heap multi-gigabyte. ZGC e Shenandoah puntano a pause inferiori al millisecondo su heap molto grandi, il che li rendetractivo per i servizi sensibili alla latenza. Scegliere il collettore giusto e ottimizzare le dimensioni di Young Generation, Old Generation e Metaspace รจ una competenza fondamentale per Java lavoro di performance.
Nota: Tutti gli oggetti vengono creati nella sezione Heap della memoria, che รจ la regione gestita dal Garbage Collector.
Esempio: Per apprendere il meccanismo di raccolta dei rifiuti in Java
Questa procedura illustra quando i riferimenti diventano idonei per la raccolta automatica all'interno di un semplice programma.
Passo 1) Copiare il codice seguente in un editor.
class Student{ int a; int b; public void setData(int c,int d){ a=c; b=d; } public void showData(){ System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); } public static void main(String args[]){ Student s1 = new Student(); Student s2 = new Student(); s1.setData(1,2); s2.setData(3,4); s1.showData(); s2.showData(); //Student s3; //s3=s2; //s3.showData(); //s2=null; //s3.showData(); //s3=null; //s3.showData(); } }
Passo 2) Salva, compila ed esegui il codice. Come mostrato nel diagramma, vengono creati due oggetti e due variabili di riferimento.
Passo 3) Rimuovi il commento dalle righe 20, 21 e 22. Salva, compila ed esegui il codice.
Passo 4) Come illustrato nel diagramma sottostante, ora due variabili di riferimento puntano allo stesso oggetto.
Passo 5) Rimuovi il commento dalle righe 23 e 24. Salva, compila ed esegui il codice.
Passo 6) Come mostrato di seguito, s2 diventa nullo, ma s3 punta ancora all'oggetto, quindi l'oggetto non รจ ancora idoneo per la Garbage Collection.
Passo 7) Rimuovi il commento dalle righe 25 e 26. Salva, compila ed esegui il codice.
Passo 8) A questo punto, non ci sono piรน riferimenti all'oggetto, quindi diventa idoneo per il Garbage Collector. Il Garbage Collector lo rimuove dalla memoria e non c'รจ modo di recuperarlo.
Come eliminare un oggetto in Java?
Java non fornisce un operatore di eliminazione manuale, quindi l'approccio standard รจ quello di rimuovere ogni riferimento all'oggetto in modo che il Garbage Collector possa recuperarlo.
1) Per rendere un oggetto idoneo alla Garbage Collection, assegna a null il valore a tutte le variabili di riferimento che puntano ad esso.
2) I tipi primitivi non sono oggetti, quindi non possono essere assegnati a null. La loro memoria viene recuperata automaticamente quando il frame Stack circostante viene estratto.


















