[PT-BR] Mark and Sweep e as gerações da heap
Tags: java, jvm, ptbr
Published: 2021-03-15 20:40:54

Um dos objetivos da **JVM** é gerenciar a memória utilizada pelos nossos sistemas. Isto é feito através de processos que são executados ao longo do ciclo de vida da aplicação. O *garbage collector* é um dos mais importantes. De forma resumida, ele é o responsável por liberar espaço na memória, coletando objetos que não estão mais sendo referenciados. A ideia deste post é explicar, em detalhes, como é feita esta coleta.

#Garbage Collector

Sempre que instanciamos um objeto na nossa aplicação, o mesmo é alocado em um espaço de memória chamado *heap*. Com o passar do tempo muitos objetos perdem suas referências e não são mais úteis para o sistema. Com um acumulo de objetos não referenciados, o *garbage collector* é invocado. O processo é chamado de *mark and sweep* e envolve dois passos. No primeiro passo é necessário descobrir quais objetos ainda possuem referência. Uma vez descobertos estes objetos serão marcados. No segundo passo, todos os outros objetos que não foram marcados estarão prontos para a coleta e é nesse momento que ocorre uma varredura para liberação do espaço de memória. Um detalhe que não foi informado é que enquanto o processo é executado, a aplicação para de rodar, com o intuito de evitar concorrência com o *garbage collector*. Essa parada é chamada de *stop the world*. Se sempre que o *garbage collector* for varrer a *heap*, os objetos que possuem referência forem marcados, elevará o tempo da parada e os usuários sentirão que a aplicação não está respondendo naquele momento, o que não é interessante. Então como fazer para melhorar o processo de coleta?

#Young e Old Generation

Para evitar o problema visto anteriormente, a *heap* foi dividida em gerações. Essas gerações são a *young generation* e a *old generation*. A *young* possui um espaço menor e é dividida em 3 partes, que são o eden, s0 e s1 (survivor espaces). Todo novo objeto será criado no eden. Conforme aumenta a quantidade de objetos no eden, o *garbage collector* é chamado, porém o processo de marcação e varredura leva menos tempo, pois conforme informado, há menos espaço destinado para a *young generation*. Após a execução do *gc*, os objetos que ainda possuem referência, serão alocados no espaço s0. Como novos objetos estão sendo criados no eden, quando o *gc* é executado, ele irá olhar para os sobreviventes do eden e do s0 e os migrará para o espaço s1. Após esse processo inicial, todos os objetos criados no eden, poderão ser migrados para o s0 ou s1, sem ordem de precedência e o *gc* atuará em todos estes espaços. Após um número *x* de execuções (a depender da **JVM** e configurações feitas pelos usuários) os objetos sobreviventes na *young generation*, serão fragmentados e movidos para a *old generation*. Na *old generation* o processo de coleta será executado apenas quando necessário, ou seja, quando não possuir mais espaço e isso ocorrerá com menor frequência. 

#Conclusão

Percebemos que o *garbage collector* é um processo extremamente importante para mantermos a performance da nossa aplicação. Porém, se fosse realizado a coleta em toda a *heap*, por existir o *stop the world*, a aplicação pararia de executar, para não concorrer com o *gc* e isso causaria uma instisfação aos usuários do sistema, que iriam sentir que a aplicação não estaria respondendo naquele momento. Isso é evitado graças as gerações da *heap*. Na *young generation* o processo de coleta é executado com maior frequência, mas de forma muito rápida, pois é um espaço menor, fazendo com que não seja percebida pelos usuários. Já na *old generation*, espaço que possui os objetos sobreviventes, o processo é executado apenas quando necessário, com uma frequência bem menor, e quando ocorre, apesar de ser sentido pelos usuários, não é tão prejudicial. O assunto do post de hoje foi curto, porém complexo, então toda crítica, dúvida ou sugestão serão bem-vindas. Espero que tenham gostado. Até o próximo.