Trabalhando com Gerações de Objetos

Os coletores de lixo Java implementam uma estratégia de coleta de lixo geracional que pode classificar objetos por idade.

Tal necessidade (de marcar e compactar todos os objetos) na JVM pode ser chamada de ineficiente. Como um grande número de objetos é alocado, sua lista cresce, o que leva a um aumento no tempo de coleta de lixo. A análise empírica de aplicativos mostrou que a maioria dos objetos em Java tem vida curta.

A área de memória heap na JVM é dividida em três seções:

Trabalhando com Gerações de Objetos

Geração mais nova

Objetos recém-criados começam na geração mais jovem. A geração mais jovem é subdividida em duas categorias.

  • Eden Space - Todos os novos objetos começam aqui, eles recebem memória inicial.
  • Survivor Spaces (FromSpace e ToSpace) - Os objetos são movidos para cá do Éden após sobreviverem a um ciclo de coleta de lixo.

O processo quando os objetos são coletados como lixo da geração mais jovem é chamado de evento secundário de coleta de lixo.

Quando o espaço do Éden está cheio de objetos, uma pequena coleta de lixo é realizada. Todos os objetos mortos são removidos e todos os vivos são movidos para um dos dois espaços restantes. O pequeno GC também verifica os objetos no espaço do sobrevivente e os move para outro (próximo) espaço do sobrevivente.

Vamos tomar a seguinte sequência como exemplo.

  1. Existem objetos de ambos os tipos (vivos e mortos) no Éden.
  2. Um pequeno GC ocorre - todos os objetos mortos são removidos do Éden. Todos os objetos vivos são movidos para o espaço-1 (FromSpace). Eden e espaço-2 agora estão vazios.
  3. Novos objetos são criados e adicionados ao Éden. Alguns objetos no Éden e no espaço-1 tornam-se mortos.
  4. Um pequeno GC ocorre - todos os objetos mortos são removidos do Éden e do espaço-1. Todos os objetos vivos são movidos para o espaço-2 (ToSpace). O Éden e o espaço-1 estão vazios.

Assim, a qualquer momento, um dos espaços sobreviventes está sempre vazio. Quando os sobreviventes atingem um certo limite para se mover pelos espaços dos sobreviventes, eles avançam para uma geração mais velha.

Você pode usar o sinalizador -Xmn para definir o tamanho da geração jovem .

geração mais velha

Objetos que vivem uma quantidade significativa de tempo (por exemplo, a maior parte do tempo de vida de um programa) acabam se tornando objetos mais antigos - centenários. Também é conhecida como a geração regular e contém objetos que foram deixados nos Espaços do Sobrevivente por muito tempo.

O limite de tempo de vida de um objeto determina por quantos ciclos de coleta de lixo ele deve passar antes de ser movido para a geração mais antiga. O processo quando os objetos são enviados para o lixo da geração mais antiga é chamado de evento principal de coleta de lixo.

Você pode usar os sinalizadores -Xms e -Xmx para definir o tamanho de memória heap inicial e máximo .

Como o Java usa coleta de lixo geracional, quanto mais eventos de coleta de lixo um objeto experimenta, mais ele avança no heap. Ele começa na geração mais jovem e eventualmente termina na geração regular se viver o suficiente.

Para entender a promoção de objetos entre espaços e gerações, considere o seguinte exemplo:

Quando um objeto é criado, ele é primeiro colocado no espaço do Éden da geração jovem.

Assim que ocorre uma pequena coleta de lixo, os objetos vivos do Éden são movidos para o FromSpace. Quando ocorre a próxima coleta de lixo menor, os objetos vivos do Éden e do espaço são movidos para o ToSpace.

Este ciclo continua um certo número de vezes. Se o objeto ainda estiver "em serviço" após esse ponto, o próximo ciclo de coleta de lixo o moverá para o espaço de geração anterior.

Geração permanente e metaespaço

Metadados como classes e métodos são armazenados em geração persistente. A JVM o preenche no tempo de execução com base nas classes usadas pelo aplicativo. Classes que não são mais utilizadas podem passar de geração permanente para lixo.

Você pode usar os sinalizadores -XX:PermGen e -XX:MaxPermGen para definir o tamanho inicial e máximo da geração permanente .

meta espaço

Desde o Java 8, o espaço PermGen foi substituído pelo espaço de memória MetaSpace. A implementação difere do PermGen - esse espaço de heap agora é alterado automaticamente.

Isso evita o problema de falta de memória do aplicativo que ocorre devido ao tamanho limitado do espaço de heap do PermGen. A memória do metaespaço pode ser coletada como lixo e as classes que não estão mais em uso serão limpas automaticamente quando o metaespaço atingir seu tamanho máximo.