Java Garbage Collection: melhores práticas, tutoriais e muito mais

O Java garbage collection é o processo pelo qual os programas Java executam o gerenciamento automático de memória. Os programas Java compilam para bytecode que pode ser executado em um Java Virtual Machine (JVM). Quando os programas Java são executados na JVM, os objetos são criados no heap, que é uma parte da memória dedicada ao programa. Eventualmente, alguns objetos não serão mais necessários. O garbage collector localiza esses objetos não utilizados e os exclui para liberar memória.

Como o Java Garbage Collection funciona

O Java garbage collection é um processo automático. O programador não precisa marcar explicitamente os objetos a serem excluídos. A implementação do garbage collection está na própria JVM. Cada JVM pode implementar o garbage collection como quiser; o único requisito é que atenda às especificações da JVM. Embora existam muitas JVMs, o HotSpot da Oracle é de longe o mais comum. Oferece um conjunto robusto e maduro de opções de garbage collection.

Embora o HotSpot tenha vários garbage collectors que são otimizados para vários casos de uso, todos os seus garbage collectors seguem o mesmo processo básico. Na primeira etapa, os objetos não referenciados são identificados e marcados como prontos para o garbage collector. Na segunda etapa, os objetos marcados são excluídos. Opcionalmente, a memória pode ser compactada após o garbage collector excluir objetos, portanto, os objetos restantes estão em um bloco contíguo no início do heap. O processo de compactação torna mais fácil alocar memória para novos objetos sequencialmente após o bloco de memória alocada para objetos existentes.

Todos os garbage collectors do HotSpot implementam uma estratégia geracional de garbage collection que categoriza objetos por idade. A racionalidade por trás do garbage collection geracional é que a maioria dos objetos é de curta duração e estarão prontos para o garbage collection logo após a criação.

Java-Garbage-Collection

A pilha é dividida em três seções:

Young Generation: Os objetos recém-criados começam no Young Generation. O Young Generation é ainda subdividido em um espaço Eden, onde todos os novos objetos se iniciam, e dois espaços Survivor, onde os objetos são movidos do Eden depois de sobreviver a um ciclo do garbage collection. Quando os objetos são coletados ao garbage collection da Young Generation, é um evento menor do garbage collection.

Old Generation: Objetos de longa duração são eventualmente movidos da Young Generation para a Old Generation. Quando os objetos são lixo coletado da Old Generation, é um grande evento de garbage collection.

Permanent Generation: Metadados como classes e métodos são armazenados na Permanent Generation. As classes que não estão mais em uso podem ser coletadas da Permanent Generation.

Durante um evento completo de garbage collection, objetos não utilizados em todas as gerações são coletados.

O HotSpot tem quatro garbage collectors:

Serial: Todos os eventos do garbage collection são conduzidos em série em uma thread. A compactação é executada após cada coleta.

Parallel: Várias threads são usadas para coleta de lixo menor. Uma única thread é usada para coleta de lixo principal e compactação da  Old Generation. Como alternativa, a variante Parallel Old usa vários segmentos para a garbage collection principal e compactação de Old Generation.

CMS (Concurrent Mark Sweep): Várias threads são usadas para garbage collection secundária usando o mesmo algoritmo que Parallel. A garbage collection principal é multi-thread, como o Parallel Old, mas o CMS é executado simultaneamente ao lado de processos de aplicativo para minimizar os eventos “stop the world” (isto é, quando o garbage collector em execução interrompe o aplicativo). Nenhuma compactação é realizada.

G1 (Garbage First): O garbage collector mais recente destina-se a ser um substituto para o CMS. É paralelo e concorrente como o CMS, mas funciona de forma bastante diferente em comparação com garbage collectors mais antigos.

Benefícios do Java Garbage Collection

O maior benefício do Java garbage collection é que ele gerencia automaticamente a exclusão de objetos não utilizados ou objetos que estão fora do alcance para liberar recursos de memória vital. Os programadores que trabalham em linguagens sem garbage collection (como C e C++) devem implementar o gerenciamento manual de memória em seus códigos.

Apesar do trabalho adicional necessário, alguns programadores argumentam a favor do gerenciamento de memória manual sobre o garbage collection, principalmente por razões de controle e desempenho. Enquanto o debate sobre as abordagens de gerenciamento de memória continua a seguir, o garbage collection é agora um componente padrão de muitas linguagens de programação populares. Para cenários em que o garbage collection está afetando negativamente o desempenho, o Java oferece muitas opções para ajustá-lo e melhorar sua eficiência.

Melhores práticas em Java Garbage Collection

Para muitos aplicativos simples, o Java garbage collection não é algo que um programador precise conscientemente considerar. No entanto, para programadores que desejam avançar suas habilidades Java, é importante entender como funciona o Java garbage collection e as maneiras pelas quais ele pode ser ajustado.

Além dos mecanismos básicos de garbage collection, um dos pontos mais importantes para entender sobre o garbage collection em Java é que ela é não-determinística e não há como prever quando o garbage collection ocorrerá em tempo de execução. É possível incluir um hint no código para executar o garbage collector com os métodos System.gc() ou Runtime.gc(), mas eles não oferecem nenhuma garantia de que o garbage collector será realmente executado.

A melhor abordagem para ajustar o Java garbage collection é configurar flags na JVM. As flags podem ajustar o garbage collector a ser usado (por exemplo, Serial, G1 etc.), o tamanho inicial e máximo do heap, o tamanho das seções de heap (por exemplo, Young Generation, Old Generation) e muito mais. A natureza do aplicativo a ser ajustado é um bom guia inicial para as configurações. Por exemplo, o Parallel garbage collector é eficiente, mas frequentemente levará a eventos “stop the world”, tornando-o mais adequado para o processamento backend onde longas pausas para o garbage collection são aceitáveis.

Por outro lado, o CMS garbage collector é projetado para minimizar pausas, o que o torna ideal para aplicações GUI onde a capacidade de resposta é importante. O ajuste fino adicional pode ser realizado alterando o tamanho do heap ou suas seções e medindo a eficiência do garbage collection usando uma ferramenta como jstat.

Recursos adicionais e tutoriais sobre Java Garbage Collection

Visite os seguintes recursos e tutoriais para obter mais informações sobre o Java Garbage Collection:

Java Garbage Collection Basics
What is the garbage collector in Java?
How to Tune Java Garbage Collection
Garbage Collectors – Serial vs. Parallel vs. CMS vs. G1 (and what’s new in Java 8)
Garbage Collection in Java
Understanding the Java Garbage Collection Log

Fonte: DZone.com

21