Os campos estáticos estão abertos para a coleta de lixo?

95

Dada uma classe de utilitário hipotética que é usada apenas na configuração do programa:

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

myObject será coletado como lixo quando não estiver mais sendo usado ou permanecerá por toda a vida do programa?

Michael Deardeuff
fonte

Respostas:

112

Variáveis ​​estáticas não podem ser escolhidas para coleta de lixo enquanto a classe é carregada. Eles podem ser coletados quando o respectivo carregador de classe (que foi responsável por carregar essa classe) é ele próprio coletado para o lixo.

Verifique a Seção 12.7 do JLS para descarregamento de classes e interfaces

Uma classe ou interface pode ser descarregada se e somente se seu carregador de classe de definição pode ser recuperado pelo coletor de lixo [...] Classes e interfaces carregadas pelo carregador de bootstrap não podem ser descarregadas.

bruno conde
fonte
@bruno, por seu link, significa que um carregador de classe contém uma referência para cada classe que carrega, mesmo se a classe carregada não tiver membros estáticos?
Pacerier
@brunoconde, não acho que isso seja verdade. Exatamente que parágrafo afirma isso? (Continue a discussão em stackoverflow.com/questions/405364/… )
Pacerier
Quando o carregador de classes estaria qualificado para a coleta de lixo. ?
Rohit Bandil
@RohitBandil - quando está inacessível.
Stephen C
55

Variáveis ​​estáticas são referenciadas por objetos Class que são referenciados por ClassLoaders - então, a menos que o ClassLoader elimine a classe de alguma forma (se isso for possível) ou o próprio ClassLoader se torne elegível para coleta (mais provavelmente - pense em descarregar aplicativos da web) as variáveis ​​estáticas (ou em vez disso, os objetos aos quais fazem referência) não serão coletados.

Jon Skeet
fonte
1
Os Classobjetos que não contêm variáveis ​​estáticas são referenciados por seu carregador de classes?
Pacerier
14

Se você quiser que um objeto temporário seja usado para inicialização estática e depois descartado, você pode usar um bloco inicializador estático, por exemplo

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

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

uma vez que o bloco inicializador estático é um tipo especial de método estático, myObject é uma variável local e pode ser coletado como lixo após o bloco terminar de ser executado.

Finnw
fonte
13

myObject é uma referência e não um objeto . Um objeto é automaticamente coletado como lixo quando nenhuma referência aponta para ele porque está inacessível.

Assim, também o objeto por trás de uma referência estática "myObject" pode ser coletado como lixo se você desreferenciá-lo com

myObject = null;

e não há outras referências a este objeto.

No entanto, as referências e variáveis ​​estáticas permanecem durante o tempo de vida do seu programa.

Felix Keil
fonte
Bem-vindo ao StackOverflow! Definir o objeto nullno final do static blocké uma opção viável. No meu caso, porém, a vida útil do objeto precisava ser mais longa do que o bloco estático. O fim de utilidade do objeto não era muito concreto; portanto, minha pergunta sobre a utilização do coletor de lixo.
Michael Deardeuff
7

Acho que isso responde à sua pergunta - basicamente, a menos que a classe venha de um carregador de classes especial e isso descarregue a classe.

Tom
fonte
0

A chave aqui é a coleta de lixo de instâncias de classe, ou seja, objetos. A instância de ClassLoader é, em essência, um objeto. Portanto, se o objeto Classloader não for coletado como lixo, quaisquer referências deles armazenadas no heap (ou seja, coisas estáticas) quase nunca serão coletadas como lixo. A exceção é String pool.

Portanto, antes que você decida fazer de repente, private static MyGiantClass myGiantObject = new MyGiantClass() pense duas vezes como aprendi da maneira mais difícil.

ha9u63ar
fonte