Coletor de lixo Java-quando ele coletar?

O que é que determina quando o coletor de lixo realmente recolhe? Isso acontece depois de um certo tempo ou depois de uma certa quantidade de memória ter sido usada? Ou há outros factores?

Author: nalo, 2009-10-17

6 answers

Ele corre quando determina que é hora de correr. Uma estratégia comum em coletores de lixo geracionais é executar o coletor quando uma alocação de memória geração-0 falha. Isto é, cada vez que você alocar um pequeno bloco de memória (grandes blocos são tipicamente colocados diretamente em gerações "mais velhas"), o sistema verifica se há espaço livre suficiente no heap gen-0, e se não houver, ele executa o GC para libertar espaço para a alocação ter sucesso. Os dados antigos são então transferidos para o Gen-1 heap, e quando o espaço é executado lá fora, o GC executa uma coleção sobre isso, atualizando os dados que tem estado lá por mais tempo para o heap gen-2, e assim por diante. Então o GC não apenas "corre". Ele pode correr apenas no heap gen-0( e a maioria das coleções fará exatamente isso), ou pode verificar cada geração se ele realmente tem que liberar um monte de memória (o que só é necessário muito raramente).

Mas isto está longe da Estratégia apenas. Um GC paralelo funciona em segundo plano, limpando enquanto o programa está em execução. Alguns GC's podem funcionar como parte de cada alocação de memória. Um coletor incremental pode fazer isso, digitalizando alguns objetos em cada alocação de memória.

O ponto inteiro de um coletor de lixo é que ele deve apenas fazer a sua coisa sem exigir qualquer entrada do Usuário. Então, em geral, você não pode, e não deve, prever quando ele vai funcionar.

Eu acredito que Suns JVM ganhou um GC geracional não muito tempo atrás (v1.6 talvez? Não codifico Java há anos, por isso ... Não tenho certeza sobre isso, mas eu me lembro de ter sido surpreendido não muito tempo atrás, quando um dos pontos de venda para a nova versão foi "um GC geracional". Até porque a. NET teve um desde o primeiro dia.)

Os outros JVM são livres de escolher a estratégia que quiserem.

EDIT: a parte acima sobre Java e GC geracional não é verdadeira. Veja abaixo para mais detalhes:

As máquinas virtuais 1.0 e 1.1 usaram um coletor de varrimento de marcas, que poderia fragmentar o heap. depois de uma recolha de lixo. Começando com Java 1.2, As máquinas virtuais mudaram para um coletor geracional, que tem um comportamento de desfragmentação muito melhor (Veja teoria e prática Java: coleta de lixo e desempenho).

Então Java realmente tem um GC geracional por idades. O que há de novo no Java 6 é o Garbage-First garbage collector (G1) que está disponível no Java 6u14. De acordo com o artigo que reclama a libertação em 1.6.0_14: não é permitido por padrao. O coletor paralelo ainda é o GC padrão e é o GC mais eficiente para uso doméstico comum. G1 é destinado a ser uma alternativa para o coletor concorrente. Ele é projetado para ser mais previsível e permitir uma alocação rápida com o design de regiões de memória.

 26
Author: jalf, 2009-10-17 18:46:09
    Depende da forma como o programa JIT foi compilado. Do lado de fora não sabemos quando irá funcionar.
  • segue um algoritmo que depende desse GC em particular.
  • A máquina virtual Java funciona na máquina cliente com alguma memória virtual no caso do Windows default ser 4GB. Também depende dessa memória virtual livre naquele momento em particular.

Você pode tentar este pequeno programa para verificar o comportamento de GC

public class GCTest {

   final int NELEMS = 50000;

   void eatMemory() {

      int[] intArray = new int[NELEMS];

      for (int i=0; i<NELEMS; i++) {
        intArray[i] = i;
      }

   }

   public static void main (String[] args) {

      GCTest gct = new GCTest();

      // Step 1: get a Runtime object
      Runtime r = Runtime.getRuntime();

      // Step 2: determine the current amount of free memory
      long freeMem = r.freeMemory();
      System.out.println("free memory before creating array: " + freeMem);

      // Step 3: consume some memory
      gct.eatMemory();

      // Step 4: determine amount of memory left after consumption
      freeMem = r.freeMemory();
      System.out.println("free memory after creating array:  " + freeMem);

      // Step 5: run the garbage collector, then check freeMemory
      r.gc();
      freeMem = r.freeMemory();
      System.out.println("free memory after running gc():    " + freeMem);
   }
}

Possível saída -- Pode ser diferente no seu caso

free memory before creating array: 4054912
free memory after creating array:  3852496
free memory after running gc():    4064184

Verifique esta ligação http://www.devdaily.com/java/edu/pj/pj010008/

 7
Author: Xinus, 2009-10-17 13:45:32
Depende muito de que coletor de lixo você está realmente usando, como está sintonizado, e um monte de entradas.

Para uma corrida para baixo do coletor de lixo HotSpot (o comum que vem com Java) e como ele está sintonizado, você pode verificar este link

 5
Author: tschaible, 2009-10-17 13:33:30
[[1]Isso depende completamente do JVM real e do que ele escolhe fazer, e está basicamente fora de suas mãos como programador. Os peritos do die-hard de pasta cinzenta podem querer dizer à JVM que sabem melhor, mas para meros mortais isto deve ser considerado magia negra, é melhor deixar isso em paz.

O que lhe deve preocupar é se ele pode acompanhar a taxa que seus programas criam e descartam objetos. Se o seu programa inteiro não estiver completo, enquanto ocorre a limpeza global. Que acontece que são tempos de resposta muito ruins, mas raramente acontece para JVM modernos em computadores modernos.

Se você está curioso sobre o que acontece em seu programa e quando, em seguida, investigar a ferramenta "jvisualvm" nas versões recentes do Java 6 JDK. É muito bom para espreitar por dentro.

 2
Author: Thorbjørn Ravn Andersen, 2009-10-17 17:23:37

O coletor de lixo funciona quando ele precisa de recursos e em uma base regular que você pode influenciar, dizendo Quando é uma boa hora para gastar CPU na coleta, usando Sistema.gc()

Você pode ajudar o coletor de lixo pelo anulamento de referências explicitamente, por exemplo, dando o seu objectos init() métodos que alocam recursos e cleanup() métodos que explicitamente limpar esses recursos e anulamento de suas referências. Ao anular referências a si mesmo, evita o lixo tye. coletor de ter que encontrar aglomerados de obetos que têm mais caminhos para uma raiz.

 1
Author: rsp, 2009-10-17 14:02:09

Quando a JVM não tem espaço de memória necessário para correr, o coletor de lixo irá correr e apagar objetos desnecessários e alocar memória para a JVM.

Objetos desnecessários são os objetos que não têm referência (endereço) para ele.

Existem principalmente 4 pontos para os objectos elegíveis para recolha de lixo.
  1. Referência Nula

    O coletor de lixo pode apagar um objeto quando a variável de referência do objeto é atribuído nulo como é valor

        A a = new A();
        a = null;
    
  2. Recolocação

    Quando outro objecto é atribuído à variável de referência de um objecto o objecto referenciado mais antigo pode ser apagado pelo lixo colector.

      A a = new A(100);
      a =new A(200);
    
  3. Âmbito De Aplicação Local

    Se um objecto é criado dentro de um bloco, esse objecto é elegível para coletor de lixo do lado de fora daquele quarteirão.

      if(condition){
    
         A a = new A();
    
      }
    
  4. Isolamento

    Um objecto pode referir outro objecto, mas deve haver pelo menos um referência (endereço) variável para estes objectos na pilha, caso contrário todos esses objetos são elegíveis para coletor de lixo.

          class A{
                A r;
                A(int i){
                 //something   
               }
          } 
    
          A a1 = new A(100);
          a1.r = new A(101);
          a1.r.r = new A(102);
          a1.r.r.r = a1;
    
          a1  = null //all ojects are eligible to garbage collector  
    
 0
Author: Nisal Edu, 2017-11-05 01:41:12