2010-03-15 13 views
46

La memoria heap è garbage collection in Java.La garbage stack è raccolta in Java?

Anche la raccolta stack viene raccolta?

Come viene recuperata la memoria dello stack?

+10

Lo stack è l'algoritmo di garbage collection originale. Anche C ha uno stack raccolto dai rifiuti! – jrockway

+0

C, C++, Java ha una garbage collection dello stack. Oltre a ciò, solo Java fornisce la garbage collection dell'heap. (dai tre sopra menzionati) –

risposta

28

Lo stack non è garbage collection in Java.

Lo stack assegnato per una determinata chiamata di metodo viene liberato quando viene restituito il metodo. Poiché si tratta di una struttura LIFO molto semplice, non è necessario eseguire la garbage collection.

Un punto in cui lo stack e la garbage collection interagiscono è che i riferimenti sullo stack sono le radici di GC (il che significa che sono i riferimenti di root da cui è definita la raggiungibilità).

+11

Per essere precisi, lo stack non contiene nulla che possa essere raccolto dalla spazzatura. Le uniche cose che contiene sono riferimenti a oggetti e valori di tipi primitivi. L'unica cosa che è soggetta alla garbage collection sono gli oggetti. Sii consapevole della differenza tra un oggetto e un riferimento ad esso. –

+0

@Roland: è quello che ho detto. Le radici di GC sono i * riferimenti *, non gli oggetti. –

+0

Lo so. Ho solo pensato che per la formulazione di questa domanda sarebbe bene essere molto espliciti su questo argomento e spiegarlo forse più del necessario. –

32

La memoria nello stack contiene parametri di metodo e variabili locali (per essere precisi: i riferimenti per gli oggetti e le variabili stesse per i tipi primitivi). Questo verrà rimosso automaticamente se lasci il metodo. Se le variabili sono riferimenti (agli oggetti) gli oggetti stessi sono nell'heap e gestiti dal garbage collector.

Quindi lo stack non è garbage collection allo stesso modo dell'heap, ma stack è una forma di gestione automatica della memoria nel suo stesso (che precede la garbage collection).

A more detailed answer is given by Thomas Pornin, esaminare per ulteriori dettagli.

0

Nessuno, i dati vengono inviati e prelevati dallo stack come si hanno variabili interne nei metodi, durante le chiamate di metodo, ecc. Non è necessario preoccuparsene.

8

La parte di stack della memoria funziona come una "pila". So che suona male, ma è esattamente come funziona. I dati vengono aggiunti in cima, uno sopra l'altro (pushed onto the stack) e vengono rimossi automaticamente dalla parte superiore (popped off the stack) durante l'esecuzione del programma. Non è raccolta dati inutili, e non è necessario poiché la memoria viene recuperata automaticamente una volta che i dati vengono estratti dallo stack. E quando dico reclamato non intendo che venga de-allocato - è solo che la posizione nella memoria dello stack in cui verranno archiviati i dati successivi viene ridotta, mentre i dati vengono saltati fuori.

Ovviamente questo non vuol dire che non sia necessario preoccuparsi dello stack. Se si esegue una funzione ricorsiva molte volte finirà per utilizzare tutto lo spazio dello stack. Lo stesso se chiamate molte funzioni, specialmente se hanno molti parametri e/o variabili locali.

Ma la linea di fondo è che la memoria della pila viene utilizzata e recuperata quando le funzioni entrano e escono dall'ambito - automaticamente. Quindi alla fine dell'esecuzione del programma tutta la memoria dello stack sarebbe libera e quindi rilasciata al sistema operativo.

1

Tutti gli oggetti in Java sono allocati nell'heap. (Almeno per quanto riguarda le specifiche, l'implementazione effettiva può allocarle sullo stack se si comportano in modo trasparente come se fossero nello heap.)

Esattamente ciò che è da collezione è un po 'sottile. Se l'unico riferimento a un oggetto si trova in un singolo stack frame e può essere mostrato che il riferimento non verrà più utilizzato, l'oggetto potrebbe essere raccolto. Se l'oggetto è usato solo per leggere un campo, allora quel campo letto può essere ottimizzato in avanti e l'oggetto raccolto prima di quanto ci si potrebbe aspettare.

Questo di solito non importa a meno che non si stiano utilizzando i finalizzatori (o presumibilmente Reference s).In tal caso, si deve prestare attenzione e utilizzare i blocchi/volatile per applicare una relazione happens-before.

Quando i thread si interrompono, in genere l'intero stack viene deallocato.

1

Tutto ciò che si trova nello stack viene considerato come root globale da un garbage collector. Quindi, sì, puoi sicuramente dire che lo stack è "garbage collection".

14

Il pacco potrebbe essere immesso nella raccolta dati. Tuttavia, nella maggior parte delle implementazioni JVM, è gestito come, beh, uno "stack", che per definizione preclude la garbage collection.

Ciò che noi chiamiamo lo stack è l'accumulo di metodo di attivazione contesti: per ogni metodo invocato, questa è la struttura concettuale che contiene gli argomenti del metodo, le variabili locali, un puntatore nascosta al contesto per il metodo di chiamata, e uno slot per salvare il puntatore dell'istruzione. Il contesto di attivazione non è accessibile come tale dal linguaggio Java stesso. Un contesto diventa inutile quando si esce dal metodo (con uno return o a causa di un'eccezione generata). Succede che quando un metodo A chiama un metodo B, è garantito che quando A riprende il controllo, il contesto per B è diventato inutile. Ciò implica che la durata del contesto per B è una sottointervallo della durata del contesto per A. Pertanto, i contesti di attivazione (per un dato thread) possono essere allocati con una disciplina LIFO ("Last In, First Out"). In parole più semplici, una pila: un nuovo contesto di attivazione viene inserito in cima alla pila di contesti, e il contesto in cima sarà il primo a essere eliminato.

In pratica, i contesti di attivazione (chiamati anche frame stack) sono concatenati, in ordine di stack, in un'area dedicata. Quell'area viene ottenuta dal sistema operativo quando viene avviato il thread e il sistema operativo lo recupera quando termina il thread. La parte superiore della pila è designata da un puntatore specifico, spesso contenuto in un registro CPU (ciò dipende dal fatto che JVM stia interpretando o compilando il codice). Il "puntatore al contesto del chiamante" è virtuale; il contesto del chiamante è necessariamente situato appena sotto nell'ordine di stack. Il GC non interviene: l'area per lo stack viene creata e recuperata in modo sincrono, dall'attività thread stessa. Questo è anche il modo in cui funziona in molte lingue come C, che non hanno affatto un GC.

Ora nulla impedisce a un'implementazione JVM di fare diversamente, ad es. allocare i contesti di attivazione nell'heap e averli raccolti dal GC. Questo in genere non viene eseguito in Java Virtual Machines poiché l'allocazione dello stack è più veloce. Ma alcuni altri linguaggi devono fare queste cose, in particolare quelli che giocano con continuations mentre si usa ancora un GC (ad esempio Scheme e la sua funzione call-with-current-continuation), perché tali giochi infrangono la regola LIFO spiegata sopra.

+0

+1 per distinguere effettivamente i contesti e gli stack di attivazione del metodo. – sleske

+0

Potrebbe anche valere la pena notare che su alcune piattaforme (specialmente su sistemi embedded) i puntatori di istruzioni salvati entrano in un'area di memorizzazione completamente diversa da argomenti di funzione, variabili locali, ecc. Per programmi che non usano mai chiamate di funzione indirette (vero per molti embedded sistemi), questo può fornire una protezione sostanziale contro l'esecuzione di codice errante. Inoltre, una tale progettazione può accelerare le cose evitando la necessità di dedicare i cicli di memoria al salvataggio o al ricaricamento del contatore del programma all'entrata/uscita della funzione (uno stack hardware opera direttamente sul contatore del programma saltando il bus della memoria). – supercat

4

Se si fa riferimento alla memoria utilizzata nello stack, non viene raccolto.
La macchina virtuale java utilizza istruzioni bytecode esplicite per riservare e rilasciare memoria nello stack, queste istruzioni sono generate dal compilatore e gestiscono la durata di primitive come int, boolean, double e riferimenti a oggetti nello stack.
Ci sono stati piani per implementare una cosiddetta ottimizzazione chiamata coda, che rimuoverà alcune voci dallo stack una volta noto che non sono più utilizzate, ma non conosco jvm che già lo supporta.
Quindi non ci sono garbage collection per lo stack stesso, solo il compilatore ha generato istruzioni push e pop per gestire l'uso della memoria.

Lo stack stesso fa parte di una discussione. Lo stack viene allocato quando viene creato l'oggetto thread e i garbage vengono raccolti dopo che il thread è stato terminato e l'oggetto thread non viene più referenziato.

0

No. Lo stack non è garbage collection in Java. Ogni thread ha il proprio stack e contiene:

  1. valori Metodo specifici (che sono di breve durata) e
  2. riferimenti agli oggetti creati sul mucchio, e vengono indicato dal metodo

Questi valori vengono inseriti come stack frame nello stack per ogni chiamata di metodo. Dato che lo stack segue l'ordine "Last-in-First-out", alla fine di ogni chiamata di metodo, ogni frame dello stack contenente tutti i dati specifici del metodo e i riferimenti agli oggetti, se presenti, vengono estratti.

Quindi, i dati nello stack vengono automaticamente puliti una volta che il metodo/programma non rientra nell'ambito.

Problemi correlati