I campi statici sono aperti per la garbage collection?


95

Data un'ipotetica classe di utilità che viene utilizzata solo nella configurazione del programma:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

myObject verrà raccolto nella spazzatura quando non viene più utilizzato o rimarrà per tutta la vita del programma?

Risposte:


112

Le variabili statiche non possono essere scelte per la garbage collection mentre la classe è caricata. Possono essere raccolti quando il rispettivo caricatore di classi (che era responsabile del caricamento di questa classe) viene esso stesso raccolto per la spazzatura.

Consulta la sezione 12.7 JLS Scaricamento di classi e interfacce

Una classe o un'interfaccia può essere scaricata se e solo se il suo class loader che lo definisce può essere recuperato dal garbage collector [...] Le classi e le interfacce caricate dal bootstrap loader non possono essere scaricate.


@bruno, secondo il tuo link, significa che un programma di caricamento classi contiene un riferimento a ogni classe che carica, anche se la classe caricata non ha membri statici?
Pacerier

@brunoconde, non credo che sia vero in realtà. Esattamente quale paragrafo lo afferma? (Si prega di continuare la discussione su stackoverflow.com/questions/405364/... )
Pacerier

Quando il programma di caricamento classi sarebbe idoneo per la garbage collection. ?
Rohit Bandil

@RohitBandil - quando è irraggiungibile.
Stephen C

55

Le variabili statiche sono referenziate da oggetti Class a cui fanno riferimento ClassLoader -quindi a meno che il ClassLoader non elimini la Classe in qualche modo (se è possibile) o lo stesso ClassLoader non diventi idoneo per la raccolta (più probabile - pensa di scaricare webapp) le variabili statiche (o piuttosto, gli oggetti a cui fanno riferimento) non verranno raccolti.


1
Gli Classoggetti che non contengono variabili statiche vengono referenziati dal loro programma di caricamento classi?
Pacerier

14

Se desideri che un oggetto temporaneo venga utilizzato per l'inizializzazione statica e poi smaltito, puoi utilizzare un blocco inizializzatore statico, ad es.

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

poiché il blocco di inizializzazione statico è un tipo speciale di metodo statico, myObject è una variabile locale e può essere garbage collection dopo che il blocco termina l'esecuzione.


13

myObject è un riferimento e non un oggetto . Un oggetto viene automaticamente sottoposto a garbage collection quando nessun riferimento lo punta perché non è raggiungibile.

Quindi anche l'oggetto dietro un riferimento statico "myObject" può essere sottoposto a garbage collection se lo si dereferenzia con

myObject = null;

e non ci sono altri riferimenti a questo oggetto.

Tuttavia, i riferimenti statici e le variabili rimangono per la durata del programma.


Benvenuto in StackOverflow! Impostare l'oggetto su nullalla fine del static blockè un'opzione praticabile. Nel mio caso, tuttavia, la durata dell'oggetto doveva essere più lunga del blocco statico. La fine dell'utilità dell'oggetto non era molto concreta; quindi la mia domanda sull'utilizzo del garbage collector.
Michael Deardeuff

7

Penso che questo risponda alla tua domanda, fondamentalmente no a meno che la classe non provenga da un caricatore di classi speciale e che scarica la classe.


0

La chiave qui è la Garbage Collection di istanze di Class, cioè Oggetti. L'istanza di ClassLoader è, in sostanza, un oggetto. Quindi, se l'oggetto Classloader non è sottoposto a garbage collection, qualsiasi riferimento ad esso memorizzato nell'heap (cioè materiale statico) non verrà quasi mai sottoposto a garbage collection. L'eccezione è il pool di stringhe.

Quindi, prima di decidere improvvisamente di fare, private static MyGiantClass myGiantObject = new MyGiantClass() pensaci due volte come ho imparato a mie spese.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.