"Oi! Resolvi dar mais uma pequena aula sobre coleta de lixo."

Como você já sabe, a própria máquina Java monitora quando um objeto se torna desnecessário e o exclui.

"Sim. Você e Rishi me contaram sobre isso antes. Não me lembro dos detalhes."

"OK. Então vamos repassar tudo de novo."

Coleta de lixo - 1

"Assim que um objeto é criado, a JVM aloca memória para ele. O interesse no objeto é monitorado por meio de variáveis ​​de referência.  Um objeto pode ser excluído durante a coleta de lixo, ou seja, o procedimento pelo qual a memória é liberada se não houver variáveis ​​que façam referência ao objeto. "

"Fale-me um pouco sobre o coletor de lixo - o que é e como funciona."

"OK. A coleta de lixo costumava acontecer no encadeamento principal. A cada 5 minutos, ou com mais frequência. Se não houvesse memória livre suficiente, a máquina Java suspenderia todos os encadeamentos e excluiria os objetos não utilizados."

"Mas essa abordagem foi abandonada agora. O coletor de lixo de última geração trabalha nos bastidores e em um segmento separado. Isso é chamado de coleta de lixo simultânea."

"Entendo. Como exatamente é tomada a decisão de deletar ou não um objeto?"

"Apenas contar o número de referências a um objeto não é muito eficaz - pode haver objetos que fazem referência uns aos outros, mas não são referenciados por nenhum outro objeto."

"Portanto, Java adota uma abordagem diferente.  Java divide os objetos em atingíveis e inacessíveis.  Um objeto é alcançável (vivo) se for referenciado por outro objeto alcançável (vivo). A acessibilidade é determinada a partir de threads. Threads em execução são sempre considerados alcançáveis ​​(vivos) , mesmo que ninguém faça referência a eles."

"OK. Acho que entendi."

"Como ocorre a coleta de lixo real — a exclusão de objetos desnecessários?"

"É simples. Em Java, a memória é dividida em duas partes por convenção e, quando chega a hora da coleta de lixo, todos os objetos vivos (acessíveis) são copiados para outra parte da memória e a memória antiga é totalmente liberada."

"Essa é uma abordagem interessante. Não há necessidade de contar referências: copie todos os objetos alcançáveis ​​e todo o resto é lixo."

"É um pouco mais complicado do que isso. Os programadores Java descobriram que os objetos geralmente são divididos em duas categorias: de longa duração (que existem durante todo o tempo em que o programa está sendo executado) e de curta duração (que são necessários em métodos e para executar funções locais). " operações)."

"É muito mais eficiente manter os objetos de vida longa separados dos de vida curta. Para fazer isso, foi necessário encontrar uma maneira de determinar a longevidade do objeto."

"Então, eles dividiram toda a memória em «gerações». Existem objetos de primeira geração, objetos de segunda geração, etc. Cada vez que a memória é limpa, o contador de geração é incrementado em 1. Se certos objetos existem em várias gerações, então eles são registrados como de longa duração."

"Atualmente, o coletor de lixo é uma parte muito complexa e eficiente do Java. Muitas de suas partes funcionam heuristicamente — com base em algoritmos que fazem suposições. Como resultado, muitas vezes ele "não escuta" o usuário."

"Significado?"

"Java tem um objeto coletor de lixo ( GC ) que pode ser chamado usando o método System.gc ()."

"Você também pode usar System.runFinalization() para forçar chamadas aos métodos finalize dos objetos a serem excluídos. Mas o fato é que, de acordo com a documentação do Java, isso não garante que a coleta de lixo seja iniciada, nem que o finalize( ) será chamado.  O coletor de lixo decide quando chamá-lo e em quê. "

"Uau! Bom saber."

"Mas há mais. Como você sabe, em Java, alguns objetos fazem referência a outros. Essa rede de referências é usada para determinar se um objeto deve ser excluído."

"E veja só. Java tem referências especiais que permitem que você influencie esse processo. Existem classes wrapper especiais para elas. Aqui estão elas:"

" SoftReference  é uma referência suave."

" WeakReference  é uma referência fraca."

" PhantomReference é uma referência fantasma."

"Uh... Isso me lembra de classes internas, classes aninhadas, classes anônimas aninhadas e classes locais. Os nomes são diferentes, mas não está claro para que servem."

"Diga, amigo, você se tornou um programador. Agora você está com raiva por causa dos nomes das classes, dizendo «eles não são informativos o suficiente e é impossível com um nome (!) determinar o que essa classe faz, como, e porque"."

"Uau. Eu nem percebi. Mas é tão óbvio."

"OK. Chega de palavras. Deixe-me falar sobre o SoftReferences."

"Essas referências foram projetadas especificamente para armazenamento em cache, embora possam ser usadas para outros fins - tudo a critério do programador."

"Aqui está um exemplo de tal referência:"

Exemplo
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"Se as únicas referências a um objeto forem suaves, ele continuará a viver e será chamado de 'alcançável suavemente'."

"Mas!  Um objeto referenciado apenas por referências suaves pode ser excluído pelo coletor de lixo se o programa não tiver memória suficiente.  Se de repente o programa não tiver memória suficiente, antes de lançar um OutOfMemoryException , o coletor de lixo excluirá todos os objetos referenciado por referências suaves e tentará novamente alocar memória para o programa."

"Suponha que um programa cliente frequentemente solicite vários dados de um programa servidor. O programa servidor pode usar um SoftReference para armazenar em cache alguns deles. tudo. É lindo!"

"Sim. Eu também gostei."

"Bem, uma pequena adição: a classe SoftReference tem dois métodos. O método get() retorna o objeto referenciado pelo SoftReference . Se o objeto foi excluído pelo coletor de lixo, o método get () começará a retornar nulo repentinamente."

"O usuário também pode limpar o SoftReference explicitamente chamando o método clear(). Nesse caso, o elo fraco dentro do objeto SoftReference será destruído."

"É tudo por agora."

"Obrigado pela história interessante, Ellie. Realmente foi muito interessante."