Cheiro de código Java: System.gc ()

Eu encontrei muitas perguntas no Stack Overflow que são mais ou menos assim:

Meu programa Java continua travando porque está ficando sem memória, mas estou ligando System.gc()para fazer a coleta de lixo manual. O que está errado?

A coleta de lixo automática do Java é uma coisa maravilhosa e permite que os desenvolvedores se concentrem em escrever código em vez de rastrear bugs, mas sinto que agora temos uma geração de programadores que não entendem os detalhes sutis do gerenciamento de memória. Se você faz desenvolvimento em Java (ou qualquer tipo de desenvolvimento de linguagem de memória gerenciada), deve pelo menos dedicar algum tempo para entender as regras de coleta de lixo.

A implementação da coleta de lixo é amplamente dependente de sua JVM, mas as regras de quando os objetos são elegíveis para coleta são as mesmas. Aqui está a documentação da Oracle sobre isso:

Um objeto é elegível para coleta de lixo quando não há mais referências a esse objeto. As referências mantidas em uma variável geralmente são descartadas quando a variável sai do escopo. Ou você pode eliminar explicitamente uma referência de objeto definindo a variável com o valor especial nulo. Lembre-se de que um programa pode ter várias referências ao mesmo objeto; todas as referências a um objeto devem ser eliminadas antes que o objeto seja elegível para a coleta de lixo.

A única coisa que gostaria de acrescentar é apontar que o objeto se torna elegível para a coleta de lixo. Na verdade, não é coletado. Sua JVM descobrirá o melhor momento para realmente fazer a coleta de lixo.

Isso nos traz de volta ao . Os Javadocs para esse método dizem que ele “executa o coletor de lixo”. Isso é um pouco enganador. Se você ler os detalhes, descobriremos que ele apenas sugere à JVM que faça a coleta de lixo. Além disso, mesmo se a sugestão for aceita, a coleta de lixo provavelmente acontecerá de forma assíncrona, então você pode não ter mais memória disponível instantaneamente.System.gc()

Se você encontrar em seu código, é provavelmente algo que deseja sinalizar para revisão. Não é necessariamente ruim, mas mostra que há um problema que está sendo resolvido de uma forma que pode ou não ser estável. Pode funcionar hoje, mas pode falhar na próxima vez que for executado. Aqui estão algumas alternativas:System.gc()

  1. Releia as regras de elegibilidade para coleta de lixo. Você pode estar segurando referências a objetos sem perceber.
  2. Ajuste seus argumentos de memória JVM e execute ferramentas de criação de perfil para descobrir o que está acontecendo e por que você parece estar ficando sem memória.

Vamos todos reconhecer que não é uma solução absoluta e você não pode confiar nela como uma correção e é provavelmente um sinal de que você tem algum código menos do que bom em suas mãos.System.gc()

Tudo bem, consegui escrever tudo isso sem fazer nenhum tipo de piada sobre coleta de lixo e cheiro de código, então acho que devo parar agora.