JVM e Coleta de Lixo¶
O código Java é compilado em arquivos de classe que contêm bytecode e metadados. Uma JVM carrega, verifica, vincula, inicializa e executa classes. Interpretação e compilação just-in-time são estratégias de implementação que preservam contratos observáveis da linguagem e da JVM.
Áreas de dados em tempo de execução¶
- cada thread possui uma pilha da JVM com quadros para as invocações de método ativas;
- objetos e arrays são geralmente alocados em um heap compartilhado;
- metadados de classe e estruturas do runtime são gerenciados separadamente pela JVM;
- métodos nativos e buffers off-heap podem consumir memória fora do heap Java.
A especificação define áreas abstratas de dados em tempo de execução, não um layout universal de memória nem um custo em bytes.
Alcance e coleção¶
Coletores de lixo recuperam objetos que não são mais alcançáveis segundo o modelo de raízes do coletor. O momento da coleta não é determinístico, e a finalização não é um mecanismo de gerenciamento de recursos. Feche arquivos, sockets e outros recursos escassos explicitamente com try-with-resources.
Diferentes coletores otimizam objetivos como throughput, tempo de pausa, consumo de memória ou escalabilidade. Um coletor não impede vazamentos de memória: reter por uma referência viva um objeto desnecessário mantém esse objeto alcançável.
Inicialização de classe¶
Inicialização de classe tem garantias de sincronização e happens-before. É uma forma segura de publicar estado estático imutável, mas ciclos de inicialização e trabalho estático pesado podem dificultar o raciocínio sobre o comportamento.
Raciocínio de desempenho¶
A compilação JIT pode realizar inlining, especializar, eliminar alocações e remover trabalho morto quando o comportamento observável é preservado. Isso explica por que ler o código-fonte e contar alocações não substitui a análise de desempenho. Da mesma forma, um log de GC ou o tamanho do heap não basta para selecionar um coletor.
Use Java Flight Recorder, análise de heap, profiling de alocação, logs GC e JMH de acordo com a pergunta. Meça cargas representativas e diferencie as distribuições de latência do throughput. O guia de depuração e análise de desempenho conecta essas ferramentas à análise de CPU, memória e concorrência orientada por hipóteses.
Exercícios¶
- Explicar como uma coleção estática pode causar um memory leak lógico.
- Contrastar exaustão de heap com exaustão de memória nativa.
- Explicar por que
System.gc()não é um contrato de ciclo de vida de recursos.