Gerenciamento de Memória Java
Antes de mais nada, vamos falar um pouco sobre a linguagem de programação orientada a objetos Java.
Foi desenvolvida na década de 90 por uma equipe de programadores chefiada por James Gosling (conhecido como o pai do Java) , na empresa Sun Microsystems e em 2008 foi adquirida pela Oracle Corporation.
A tecnologia é vastamente utilizada no desenvolvimento de sistemas de servidores e desenvolvimento de aplicações no geral, mais de 90% das empresas selecionadas pela Fortune 500 dependem de Java para operar seus produtos e serviços. Apesar de sua idade, a linguagem é estável e não vai se aposentar tão cedo. Isso faz do Java uma das mais desejáveis entre os programadores em 2020, segundo o IEEE.
A linguagem Java é compilada para um bytecode, que é interpretada pelas Máquinas Virtuais Java (JVMs). É essa característica que faz com que os programas Java sejam independentes de plataforma, executando em qualquer sistema que possua uma JVM.
Bom, agora que você já sabe o que é o Java e uma JVM, vamos falar um pouco sobre o funcionamento e gerenciamento de memória na JVM.
Memória na JVM
Internamente, a JVM mantém uma área de memória dividida em duas partes: Heap e “Não-Heap”, onde todos os objetos criados durante a execução da aplicação e metadados das classes são gerados.
Estrutura de Memória Heap até o Java 7
Estrutura de Memória Heap a partir do Java 8
Como visto acima, podemos dividir a Memória Heap em três partes:
1. Young Generation (Geração Jovem)
A Geração Jovem é dividida em 3 espaços:
Eden Space e Survivor Space que obtém os espaços Survivor 0 e Survivor 1.
Toda a criação de objetos será armazenada no Eden Space, com isso, sempre que a JVM não consegue alocar espaço para um novo objeto o GC (Garbage Collector) excluirá todos os objetos não utilizados e não referenciados, onde esse mecanismo será chamado de GC Minor.
O GC Minor moverá todos os objetos sobreviventes para o Survivor 0, quando o Survivor 0 estiver cheio, os próximos objetos serão direcionados para o Survivor 1.
Os objetos que sobreviverem na Geração Jovem, serão movidos para Geração Antiga.
2. Old Generation (Geração Antiga)
Quando a Geração Antiga é preenchida com objetos, o GC Major ou também conhecido como “Full GC” é acionado.
Muitos Full GCs são acionados por GCs Minor, onde ocorre a limpeza de toda a Heap, com isso, vemos em diversos casos erros de timeout onde o tempo de limpeza do GC se torna elevado.
3. Permanent Generation/ Metaspace
Permanent Generation (Geração Permanente)
A Geração Permanente (presente até o Java 7), é considerada não-heap e é onde consiste na alocação de todos os métodos estáticos, variáveis primitivas e referências aos objetos estáticos.
Além disso, ele contém dados sobre bytecode, nomes e informações JIT. Antes do Java 7, o String Pool também fazia parte dessa memória.
Metaspace
Este é um novo espaço de memória a partir do Java 8, substituindo o espaço Permanent Gerenation que vimos acima. A vantagem do Metasspace é que o GC será acionado automaticamente para remover as classes mortas quando o uso de metadados da classe atinge seu tamanho máximo de metasspace.
Com essa melhoria, a JVM reduz a chance de obter o erro OutOfMemory.
Ah, se você está gostando dos nossos conteúdos, não esqueça de deixar o seu Like👍 e compartilhar com seus amigos.
Siga também o nosso canal no Youtube, onde falamos sobre dicas e melhores práticas de testes de Performance 🚀🧨😁