Coletores de lixo da JVM
*1. Visão geral *
Neste tutorial rápido, mostraremos o básico de diferentes implementações da _JVM Garbage Collection (GC) _. Além disso, descobriremos como habilitar um tipo específico de coleta de lixo em nossos aplicativos.
===* 2. Breve introdução à coleta de lixo *
A partir do nome, parece que Garbage Collection trata da localização e exclusão do lixo da memória. No entanto, na realidade, Garbage Collection rastreia todos os objetos disponíveis no espaço de heap da JVM e remove os não utilizados.
Em palavras simples, GC funciona em duas etapas simples, conhecidas como Mark e Sweep:
-
Mark - é onde o coletor de lixo identifica quais pedaços de memória estão em uso e quais não estão
-
Varredura - esta etapa remove os objetos identificados durante a fase "marca"
*Vantagens:*
-
Nenhuma manipulação manual de alocação/desalocação de memória, porque o espaço de memória não utilizado é tratado automaticamente por GC
-
Nenhuma sobrecarga de manipulação _https://en.wikipedia.org/wiki/Dangling_pointer [Dangling Pointer] _
-
Gerenciamento automático de https://en.wikipedia.org/wiki/Memory_leak [vazamento de memória] _ (o _GC por si só não pode garantir a solução completa à prova de vazamento de memória, no entanto, ele cuida de boa parte dele)
Desvantagens:
-
Como JVM precisa acompanhar a criação/exclusão de referência de objeto, essa atividade requer mais energia da CPU além do aplicativo original. Isso pode afetar o desempenho de solicitações que exigem muita memória
-
Os programadores não têm controle sobre o agendamento do tempo da CPU dedicado à liberação de objetos que não são mais necessários
-
O uso de algumas implementações de GC pode resultar na interrupção imprevisível do aplicativo *O gerenciamento automatizado de memória não será tão eficiente quanto a alocação/desalocação manual apropriada de memória
===* 3. Implementações do GC *
A JVM possui quatro tipos de implementações GC:
-
Coletor de Lixo Serial
-
Coletor de Lixo Paralelo
-
Coletor de lixo do CMS *Coletor de lixo G1
====* 3.1 Coletor de lixo serial *
Esta é a implementação mais simples do GC, pois basicamente funciona com um único encadeamento. Como resultado,* essa implementação GC congela todos os threads do aplicativo quando é executada *. Portanto, não é uma boa ideia usá-lo em aplicativos multithread como ambientes de servidor.
No entanto, houve uma excelente conversa dos engenheiros de Twitter na QCon 2012 sobre o desempenho do Serial Garbage Collector - que é uma boa maneira de entender melhor esse colecionador.
O GC serial é o coletor de lixo preferido para a maioria dos aplicativos que não possuem requisitos de tempo de pausa pequenos e são executados em máquinas no estilo do cliente. Para ativar o Serial Garbage Collector, podemos usar o seguinte argumento:
java -XX:+UseSerialGC -jar Application.java
3.2 Coletor de Lixo Paralelo
É o GC padrão da JVM e, às vezes, é chamado de coletores de taxa de transferência. Diferentemente do Serial Garbage Collector, este usa vários encadeamentos para gerenciar o espaço de heap . Mas também congela outros encadeamentos de aplicativos ao executar GC.
Se usarmos esse GC, podemos especificar o máximo de coleta de lixo threads e tempo de pausa, taxa de transferência e pegada (tamanho da pilha).
O número de encadeamentos do coletor de lixo pode ser controlado com a opção da linha de comandos _-XX: ParallelGCThreads = <N> _.
A meta de tempo máximo de pausa (intervalo [em milissegundos] entre dois GC) é especificada com a opção da linha de comandos _-XX: MaxGCPauseMillis = <N> _.
O destino de taxa de transferência máxima (medido em relação ao tempo gasto na coleta de lixo versus o tempo gasto fora da coleta de lixo) é especificado pela opção da linha de comando -XX: GCTimeRatio = <N> .
A pegada máxima do heap (a quantidade de memória heap que um programa requer durante a execução) é especificada usando a opção -Xmx <N> .
Para ativar o Parallel Garbage Collector, podemos usar o seguinte argumento:
java -XX:+UseParallelGC -jar Application.java
3.3 Coletor de lixo do CMS
A implementação _Concurrent Mark Sweep (CMS) _ usa vários threads de coletor de lixo para coleta de lixo. Ele foi projetado para aplicativos que preferem pausas mais curtas na coleta de lixo e que podem compartilhar recursos do processador com o coletor de lixo enquanto o aplicativo está em execução.
Simplificando, os aplicativos que usam esse tipo de GC respondem mais lentamente, em média, mas não param de responder para executar a coleta de lixo.
Um ponto rápido a ser observado aqui é que, como esse GC é simultâneo, uma chamada de coleta de lixo explícita, como usar System.gc () _ enquanto o processo simultâneo estiver funcionando, resultará em https://blogs.oracle.com/jonthecollector/entry/what_the_heck_s_a [_Falha no modo simultâneo/interrupção].
Se mais de 98% do tempo total for gasto na coleta de lixo CMS e menos de 2% do heap for recuperado, um OutOfMemoryError será lançado pelo CMS collector. Se necessário, esse recurso pode ser desativado adicionando a opção -XX: -UseGCOverheadLimit à linha de comandos.
Esse coletor também possui um modo conhecido como modo incremental que está sendo descontinuado no Java SE 8 e pode ser removido em um release principal futuro.
Para habilitar o CMS Garbage Collector, podemos usar o seguinte sinalizador:
java -XX:+UseParNewGC -jar Application.java
3.4 Coletor de lixo G1
G1 (Garbage First) Garbage Collector foi projetado para aplicativos em execução em máquinas com vários processadores com amplo espaço de memória. Está disponível desde a JDK7 Update 4 e em versões posteriores.
O coletor G1 substituirá o coletor CMS, pois é mais eficiente em termos de desempenho.
Diferentemente de outros coletores, o coletor G1 particiona o heap em um conjunto de regiões de heap de tamanho igual, cada um um intervalo contíguo de memória virtual. Ao executar coletas de lixo, G1 mostra uma fase de marcação global simultânea (ou seja, fase 1, conhecida como _Marking) _ para determinar a vitalidade dos objetos em todo o heap.
Após a conclusão da fase de marcação, G1 sabe quais regiões estão na maior parte vazias. Ele é coletado nessas áreas primeiro, o que geralmente gera uma quantidade significativa de espaço livre (ou seja, fase 2, conhecida como Sweeping) . É por isso que esse método de coleta de lixo é chamado Garbage-First.
Para ativar o G1 Garbage Collector, podemos usar o seguinte argumento:
java -XX:+UseG1GC -jar Application.java
3.5 Alterações no Java 8
O Java 8u20 introduziu mais um parâmetro JVM para reduzir o uso desnecessário de memória, criando muitas instâncias da mesma String. Isso otimiza a memória heap removendo valores String duplicados em um único array global _char [] _.
Este parâmetro pode ser ativado adicionando - XX: + UseStringDeduplication como parâmetro JVM.
4. Conclusão
Neste tutorial rápido, vimos as diferentes implementações da JVM Garbage Collection e seus casos de uso.
Documentação mais detalhada pode ser encontrada em aqui.