Java Desenvolvimento

Java: new generation, old generation e permanent generation na JVM

Neste artigo, abordaremos a new generation, a old generation e a permanent generation na JVM, compreendendo a função de cada uma destas áreas.

há 4 anos 7 meses

Formação Desenvolvedor Java
Conheça a formação em detalhes

Na maioria das linguagens gerenciadas e que funcionam com base no conceito de máquina virtual, a área de memória que pode ser utilizada para alocar variáveis e objetos costuma ser dividida em pelo menos duas regiões: a stack, onde os value-types ficam armazenados; e a heap, onde os reference-types ficam armazenados. Aqui no blog, escrevi um artigo onde comento sobre estas duas regiões de memória e suas implicações dentro da CLR, a máquina virtual do .NET. Se você quiser dar uma olhadinha, você pode ver aqui: C# Gerenciamento de memória no C#: stack, heap, value-types e reference-types. Apesar de o artigo ser baseado no .NET, o funcionamento é o mesmo para quase todas as linguagens baseadas em máquinas virtuais.

Quando falamos de maneira específica sobre o Java, a JVM ainda tem mais divisões criadas dentro da heap durante o seu processo de gerenciamento de memória: estamos falando da young generation e da old generation. Em adição, ainda podemos ter a permanent generation, que não fica na heap, mas desempenha um papel importante no que diz respeito ao processo de gerenciamento de memória da JVM. Vamos observar o papel de cada uma dessas divisões no processo de gerenciamento de memória dentro da JVM.

Especialista Spring
Formação Especialista Spring
Conhecer a formação

New generation (NewGen)

A new generation armazena os objtetos que tenham sido instanciados mais recentemente através da palavra-chave new. Isso quer dizer que, assim que você instancia um novo objeto de qualquer tipo no Java, esse objeto é armazenado dentro da new generation. Essa área pode ser ainda dividida em outras duas sub-áreas:

  • eden space: é a sub-divisão na qual os objetos são inicialmente armazenados dentro da new generation. Logo após a operação de geração de instância de um objeto, ele é imediatamente armazenado nesta área;
  • survivor space: é a sub-divisão para a qual os objetos são movidos quando estes sobrevivem a um ciclo menor de varredura do garbage collector.

Como o Java é uma linguagem gerenciada baseada em máquina virtual, existe um componente importantíssimo relacionado a todo esse processo de gerenciamento de memória: o garbage collector. O garbage collector é responsável por, como o nome indica, recolher o “lixo” gerado durante a execução de nossas aplicações na JVM. É ele quem libera espaços de memória que antes eram alocados por objetos que não estão sendo mais utilizados. O garbage collector pode se basear, por exemplo, em um reference counter para determinar quando um objeto está sendo utilizado ou não… A estratégia do garbage collector vai depender majoritariamente da implementação da JVM que estiver sendo utilizada.

O garbage collector trabalha em ciclos, sendo que em cada um destes ciclos uma porção da memória é analisada. Um dos menores ciclos que pode ser realizado é a análise do eden space. Se o objeto sobrevive a este ciclo de análise do eden space (ou seja, ele ainda é utilizado), ele é movido automaticamente para o survivor space. O survivor space também tem seu ciclo de varredura, mas trata-se de um ciclo mais espaçado. Isso diminui a carga de análise do garbage collector: se um objeto foi movido para o survivor space, trata-se de um objeto que é mais utilizado durante a execução de nossa aplicação, podendo ser “deixado um pouquinho de lado” pelo garbage collector.

Old generation (OldGen)

A old generation, que também é chamada de tenured generation, armazena os objetos que tenham sobrevivido aos ciclos menores de verificação do garbage collector na young generation.

O garbage collector também atua na old generation, porém, de maneira mais espaçada ainda. Por isso, dizemos que os objetos armazenados dentro da old generation são objetos de longa duração, pois eles só poderão ser removidos da memória após estes ciclos maiores do garbage collector sob a old generation. Também em contraponto, os ciclos do garbage collector que atuam sob a old generation são chamados de major cycles, enquanto os ciclos sob a new generation são chamados de minor cycles.

Permanent generation (PermGen)

A permanent generation não fica exatamente na heap: trata-se na verdade de uma porção de memória para duas estruturas distintas: meta-informações e estruturas estáticas. É nesta área que a JVM armazena as estruturas das classes utilizadas pela aplicação ou as referências a objetos e métodos estáticos que tenhamos feito em nosso código. A estrutura dos tipos primitivos também ficam armazenadas na permanent generation.

Em versões anteriores ao Java 8, a permanent generation tinha uma limitação importante: seu tamanho era limitado a 64MB em sistemas operacionais x86 e em 82MB em sistemas operacionais x64. Por isso, desde o Java 8, algumas implementações da JVM trocaram a implementação da permanent generation por uma nova implementação, chamada de metaspace. A função do metaspace é exatamente a mesma da permanent generation, com a diferença que o metaspace tem tamanho dinâmico. Isso reduz as chances de escrevermos um código que gere uma runtime exception do tipo OutOfMemory, por exemplo.

No final, podemos representar de maneira básica as áreas de memória relacionadas à heap da seguinte maneira:

Entender a maneira como a JVM lida com a memória e a alocação de memória é essencial para compreendermos algumas situações que são relativamente rotineiras mas que se apresentam muitas vezes como algo esotérico ou imcompreeensível. Em um próximo artigo, vamos abordar uma dessas situações: o stop-the-world.

Autor(a) do artigo

Cleber Campomori
Cleber Campomori

Líder de Conteúdo/Inovação. Pós-graduado em Projeto e Desenvolvimento de Aplicações Web. Certificado Microsoft MCSD (Web).

Todos os artigos

Artigos relacionados Ver todos