1. Escolher a pergunta e o artefacto
Um incidente de memória pode exigir respostas diferentes: quando a aplicação esteve em pausa, que objetos cresceram ou que categoria de memória pressiona o processo. Logs de GC ajudam a reconstruir atividade de recolha; heap dumps mostram objetos e referências segundo o formato; javacores fornecem contexto da JVM, threads e resumos úteis. Nenhum artefacto substitui todos os outros. Confirma produto, JVM e versão antes de escolher ferramentas. A documentação OpenJ9 atual serve aqui para conceitos de diagnóstico, sem afirmar que todas as opções recentes existem no IBM Java usado por uma instalação traditional. Planeia recolha, espaço e acesso aos ficheiros, pois diagnósticos podem conter dados da aplicação.
2. Medir pausas sem duplicar eventos
Um ciclo de GC pode conter fases e, consoante a política, trabalho concorrente com a aplicação. Somar a duração do ciclo e das suas fases internas conta tempo duas vezes. No exercício, recebem-se intervalos exclusivos já classificados, completos e sem sobreposição da mesma JVM. Se somam 4,8 segundos numa janela de sessenta segundos, representam oito por cento da janela. Este valor não é percentagem de CPU nem percentil de latência. Para analisar impacto, sobrepõe os períodos de pausa à cronologia dos pedidos e da carga. Uma única pausa longa e várias pausas curtas podem ter a mesma soma, mas consequências diferentes para os objetivos de resposta.
3. Distinguir crescimento e retenção indevida
Após recolhas globais comparáveis, observa-se 2,1, 2,3 e 2,2 GiB de ocupação. Estes três valores não demonstram uma fuga. Uma cache pode aquecer e estabilizar; outra pode manter referências para além do prazo pretendido. A investigação precisa de conhecer limites, expiração e volume de trabalho. Analisa tendência suficientemente longa e objetos dominantes com a equipa de desenvolvimento. Mesmo quando há crescimento, o problema pode ser capacidade insuficiente para dados legitimamente necessários. A função de suporte é apresentar hipóteses e evidência, incluindo o que ainda falta medir. Evita converter qualquer valor após GC numa classificação automática de fuga ou de saúde perfeita.
4. Compreender tamanho próprio e memória retida
Shallow heap representa o tamanho do próprio objeto; retained heap relaciona-se com o conjunto que deixaria de ser alcançável se esse objeto deixasse de o ser. Num grafo sintético, uma root alcança A de dez bytes e apenas A alcança B de noventa bytes. A tem shallow de dez e retained de cem. Se existir também um caminho da root diretamente para B, retirar A deixa B alcançável e o retained de A passa a dez. Este modelo ensina alcançabilidade, não o layout real de Java. Na análise com MAT, distingue dominância de referência direta e confirma o que o formato permite observar; alguns dumps não incluem informação completa sobre roots.
5. Ler decomposições de memória e limites
Num resumo hierárquico sintético, VM=300 MiB contém Heap=200, Threads=60 e Outros=40. O ramo representa trezentos, não seiscentos MiB: o pai já contém os filhos. NATIVEMEMINFO apresenta categorias de alocações virtuais conhecidas pela JVM e não deve ser tratado como medição completa de RSS. Confirma se a ferramenta do sistema operativo reporta memória virtual ou residente e que alocações estão cobertas. Xmx limita o heap Java, não todo o processo. Stacks, JIT e bibliotecas também precisam de margem. Aumentar heap para resolver qualquer erro de memória pode agravar pressão fora dele. A análise deve relacionar categorias, limites e evolução da carga.
6. Comparar recolhas e comunicar a hipótese
Endereços de objetos podem mudar com GC, mesmo entre dumps do mesmo processo. Para comparar evolução, usa agregados por classe e contexto, retidos e histograma, com atenção ao class loader, fase de recolha e mistura de pedidos. Uma subida na contagem não identifica automaticamente quais objetos concretos persistiram. Regista diferenças de carga antes de atribuir crescimento a uma alteração de código. Numa reunião de incidente, apresenta a observação, a hipótese, a experiência seguinte e o critério que a enfraqueceria. As atividades desta aula usam grafos e números fictícios. Não foi gerado um heap dump real nem demonstrada uma correção de fuga numa instalação WebSphere.
SYNTHETIC EVIDENCE / DADOS SINTÉTICOS
window_ms = 60000
exclusive_pause_ms = [1200, 1200, 2400]
pause_fraction = 4800 / 60000 = 0.08
root -> A(10 bytes) -> B(90 bytes)
retained(A) = 100 bytes
additional edge: root -> B
retained(A) = 10 bytesGrafo didático: root → A(10) → B(90). Retirar A torna cem bytes inalcançáveis. Com root → B adicional, retirar A liberta apenas os dez bytes de A no modelo.
Armadilhas comuns
Somar pai e filhos, confundir duração de ciclo com pausa, tratar endereços como identidades persistentes ou considerar Xmx um limite de toda a memória.
Tópicos relacionados: Javacore e heap dump · GC e tempo de resposta · Alcançabilidade e dominadores
Escolhe a evidência pelo tipo de memória e pela hipótese; calcula sem duplicações e distingue retenção observada da necessidade funcional.
Referência: Verbose garbage collection logs · DR WebSphere traditional ND 9.0.5; maintenance baseline 9.0.5.29 (2026-09-08); documentation reviewed 2026-09-30