2009-03-13 12 views

risposta

76

I metodi statici sono solo metodi, non sono memorizzati nell'heap, semplicemente non utilizzano un parametro "questo".

Le variabili statiche fungono da "radici" del GC. Di conseguenza, a meno che tu non li imposti esplicitamente a null, vivranno finché il programma vive, e così è tutto raggiungibile da loro.

Una situazione è considerata una perdita di memoria solo se si intende che la memoria diventi libera e non diventi libera. Se si intende che la variabile statica contenga un riferimento a un oggetto per una parte del tempo e si dimentichi di impostarlo su null quando si è finito con quell'oggetto, si rischia di provocare una perdita. Tuttavia, se lo si inserisce nella variabile statica e si prevede che esso rimanga lì per tutto il tempo in cui il programma è in esecuzione, allora non è sicuramente una perdita, è più probabile un "singleton permanente". Se l'oggetto è stato recuperato mentre volevi che esistesse ancora, sarebbe stato molto brutto.

Come per la domanda sull'heap: Tutti gli oggetti in Java esistono nell'heap o nello stack. Gli oggetti vengono creati sullo heap con il nuovo operatore. Un riferimento è quindi allegato a loro. Se il riferimento diventa nullo o non rientra nell'ambito (ad esempio, la fine del blocco), il GC si rende conto che non c'è modo di raggiungere quell'oggetto mai più e lo reclama. Se il riferimento è in una variabile statica, non rientra mai nell'ambito ma è comunque possibile impostarlo su null o su un altro oggetto.

+0

IIRC i campi statici saranno GCed non appena la classe che li dichiara è GCed.Se l'istanza elast della classe è sparita, la dichiarazione di classe andrà e i campi statici con esso. – ordnungswidrig

+1

Non sono sicuro che @ o11rig sia completamente preciso, ma credo che il GC sia autorizzato a raccogliere le statiche per le classi che non hanno membri in determinate circostanze. L'ho sentito da un paio di fonti, ma non ho mai sentito una spiegazione esatta. –

+0

Debole cavillo: tutti gli oggetti Java * * vivono nell'heap. Oggetti * riferimenti * e primitive possono essere memorizzati nello stack se sono locals del metodo attualmente in esecuzione e vengono memorizzati nell'heap in altro modo. (Tranne che in qualsiasi JVM moderna con JIT, dove l'ottimizzatore del JIT può mettere gli oggetti dove vuole, purché * agisca * come gli oggetti siano sullo heap.) E si potrebbe sostenere che i metodi statici - o , almeno, il bytecode Java che li implementa - vive anche nell'heap, come parte dell'oggetto Class che rappresenta la classe in cui sono stati definiti. –

1

Finché è possibile fare riferimento a queste variabili da qualche parte nel codice che non è possibile tramite GCed, ciò significa che saranno lì fino alla fine dell'applicazione.

Si può chiamare una perdita di memoria, non la chiamerei una perdita di memoria, di solito una perdita di memoria è la memoria che normalmente si aspetta di recuperare ma non si esegue mai, o si recupera solo una parte di esso. Anche le perdite di memoria di solito peggiorano nel tempo (ad esempio: ogni volta che si chiama un metodo, più memoria è "trapelata"), tuttavia in questo caso l'utilizzo della memoria per tali variabili è (tipo) statico.

+0

Non è necessario fare riferimento alle variabili statiche dal proprio codice ... il caricatore di classi contiene un riferimento permanente e pertanto il GC non eseguirà mai il kick-in. – ReneS

1

Non provoca una perdita di memoria nel senso classico C ... Ad esempio

Class A{ 

static B foo; 

... 

static void makeFoo(){ 
    foo = new B(); 
    foo = new B(); 
} 

In questo caso, una chiamata a makeFoo() non si tradurrà in una perdita di memoria, come la prima istanza può essere raccolta dalla spazzatura.

2

Gli oggetti referenziati direttamente o indirettamente dalla statistica rimarranno nell'heap fino a quando non sarà possibile raccogliere il caricatore classe appropriato. Esistono casi (ThreadLocal, ad esempio) in cui altri oggetti fanno riferimento indirettamente al programma di caricamento classe che lo fa rimanere non ritirato.

Se si dispone di un elenco statico, ad esempio, e si aggiungono riferimenti ad esso dinamicamente, quindi si può facilmente finire con "problemi di conflitto di durata dell'oggetto". Evitare statiche mutabili per molte ragioni.

3

Se si dispone di una mappa di hash statica e si aggiungono dati ad essa ... i dati non scompariranno mai e si verificherà una perdita, nel caso in cui non siano più necessari i dati. Se hai bisogno dei dati, non è una perdita, ma una grande quantità di memoria in giro.

+0

Assume che l'hashmap statico contenga molti oggetti; e ho reso il riferimento della mappa a null (non tutti gli oggetti che contiene)? è una perdita di memoria? dal momento che hai dichiarato che "il caricatore di classi mantiene permanentemente un riferimento statico e quindi il GC non eseguirà mai kick in"? –

+0

Se si imposta il riferimento statico su null e la mappa non è stata referenziata altrove, la memoria verrà liberata. Anche gli oggetti di riferimento in quello mappato verranno liberati se non vengono referenziati da qualcun altro. – ReneS

Problemi correlati