Citação FinalReference
Esta classe é um tipo de pacote, indicando que não é uma parte pública e herda da referência, o que significa que também é um tipo de referência específico. Portanto, antes que cada objeto embrulhado seja reciclado, ele será colocado no referembcequee especificado.
Este objeto de referência é usado especificamente para a classe com métodos finalizados. Pode -se entender que todo objeto com métodos correspondentes será encapsulado como um objeto FinalRefernece.
Como o método Finalize é definido pelo objeto, sua implementação padrão está vazia. Então, se esse método for reescrito, o corpo do método definitivamente não estará vazio. Essa diferença pode ser feita com isso. Enquanto o método finalizado implementar uma classe que não está vazia, os objetos gerados precisam ser registrados no FinalRefernece.
Esta etapa pode ser registrada de acordo, chamando o método do construtor padrão do objeto durante o NewInstance.
Finalizador#Método de registro
Quando esse método é chamado principalmente, o objeto Finalizador correspondente será gerado e o objeto Finalizador é herdado da FinalReference. Este método é declarado da seguinte maneira:
/ * Invocado por vm */estático void Register (objeto Finalizee) {Novo Finalizador (Finalizee);} Como pode ser visto nos comentários acima, esse método será chamado pela JVM em um período específico.
Em seguida, mude para o construtor do Finalizador, como mostrado abaixo:
Finalizador privado (objeto finalizee) {super (finalizee, fila); adicionar();} Pode -se observar que o objeto de referência correspondente será chamado de volta através da fila. A função do ADD é salvar todos os objetos que ainda não finalizaram o método e chamá -lo no System.shutdown final.shutdown. Defina -o no Runtime#runFinalizersOnExit .
Referencequeue
Esta fila de referência será colocada nesta fila antes que os objetos internos do objeto de referência correspondentes sejam reciclados (a descrição detalhada será explicada em outro artigo sobre referência.), Porque apenas o objeto correspondente precisa ser obtido nesta fila, então esse objeto está definitivamente pronto para ser reciclado.
Em seguida, chame o método finalizado correspondente antes da reciclagem.
Finalizador Threadread
Este thread continua obtendo dados da fila e chama o método Finalize correspondente. O código correspondente é o seguinte:
para (;;) {try {Finalizador f = (Finalizador) Queue.remove (); F.Runfinalizer (JLA); } catch (interruptedException x) {// ignore e continue}}O Runfinizer correspondente é o seguinte:
sincronizado (this) {if (hasbeenfinalized ()) return; remover ();} tente {objeto finalize = this.get (); if (finalizee! = null &&! (finalizee instanceof java.lang.enum)) {jla.invokefinalize (finalizee); / * Clear Stack Slot contendo essa variável, para diminuir as chances de retenção falsa com um GC */ finalizee conservador = nulo; }} Catch (throwable x) {} super.clear ();Na lógica acima, a primeira chamada remova e remova -a da finalização. Esse método é garantir que a finalização de cada objeto seja chamada apenas de uma vez, ou seja, a chamada atual é concluída. Ele será registrado no estado correspondente, isto é, hasefinfinalized Returns True (na verdade, significa apontar o próximo ponteiro nele. Ou seja, nunca foi finalizado e não há necessidade de chamar Finalize novamente).
Em seguida, é chamar o método finalizado correspondente. jla.invokeFinalize acima é realmente chamar o método finalizado do objeto correspondente. Nesse processo, o objeto original é obtido pela primeira vez através do GET. Em todo o processo da JVM, a referência não está definida como NULL antes da reciclagem para a FinizeReference. Porque aqui, o objeto de referência correspondente sempre pode ser obtido.
Após o processamento, o Clear correspondente é finalmente chamado para limpar a referência correspondente. Isso alcança o efeito da referência final não ter outro objeto para referência.
No processamento acima, não há limite para o tempo para chamar finalizar. Portanto, uma vez que a finalização de um objeto for chamada lentamente, isso afetará a execução de toda a cadeia de reciclagem e uma exceção de OOM correspondente será gerada. Portanto, a menos que, em casos especiais, não reescreva finalizar. Deve haver outros métodos para lidar com os cenários correspondentes. Por exemplo, FinalizableReference em goiaba.
Finalizador inicia o tópico
No thread acima, ele será iniciado durante a inicialização do processo correspondente. Pode -se entender que o objeto desencadeia a inicialização da classe Finalizadora chamando register(object) . Então, no bloco de inicialização estática, o encadeamento de reciclagem correspondente será iniciado. O código de inicialização correspondente é o seguinte:
static {threadGroup tg = thread.currentThread (). getThreadGroup (); para (ThreadGroup tgn = tg; tgn! = null; tg = tgn, tgn = tg.getParent ()); Finalizador de threads = novo FinalizerThread (TG); Finalizador.SetPriority (Thread.max_priority - 2); finalizer.setDaemon (true); Finalizador.start ();}A estática acima é um bloco de inicialização estática, ou seja, desde que o finalizador de classe seja usado, a chamada correspondente será acionada. O grupo de threads usado aqui é um grupo de threads do sistema, e a prioridade ainda é relativamente alta e é configurada como um encadeamento de segundo plano.
Ao usar o jstack para imprimir threads, os threads mostrados abaixo da figura aparecem são iniciados aqui. Como mostrado na figura abaixo
Resumir
Todo o finalizador trabalha em conjunto através da Final Reference pela JVM e das classes Java correspondentes. Nem tudo é implementado pela JVM, portanto, pode -se considerar que não é muito subjacente, mas para implementar a semântica correspondente. Tudo é feito por Java normal e cooperado pela JVM. Compreender todo o processo também é uma compreensão do mecanismo de corrida do próprio Java.