Cita de FinalReference
Esta clase es un tipo de paquete, que indica que no es una parte pública y hereda de la referencia, lo que significa que también es un tipo de referencia específico. Por lo tanto, antes de que cada objeto envuelto en él sea reciclado, se colocará en el referente especificado.
Este objeto de referencia se usa específicamente para la clase con métodos finalizados. Se puede entender que cada objeto con métodos correspondientes se encapsulará como un objeto FinalRefernece.
Debido a que el método finalizar está definido por Object, su implementación predeterminada está vacía. Entonces, si este método se reescribe, el cuerpo del método definitivamente no estará vacío. Esta diferencia se puede hacer a través de esto. Mientras el método finalizar implementa una clase que no está vacía, los objetos generados deben registrarse en FinalReferNece.
Este paso se puede registrar en consecuencia llamando al método del constructor predeterminado del objeto durante NewInstance.
Finalizador#Método de registro
Cuando se llama principalmente a este método, se generará el objeto finalizador correspondiente, y el objeto finalizador se hereda de FinalReference. Este método se declara de la siguiente manera:
/ * Invocado por VM */Static Void Register (Object Finalizee) {New Finalizer (finalizee);} Como se puede ver en los comentarios anteriores, JVM llamará a este método en un período específico.
Luego cambie al constructor de Finalizer, como se muestra a continuación:
Finalizador privado (Finalizee de objetos) {super (finalizee, cola); agregar();} Se puede ver que el objeto de referencia correspondiente se volverá a llamar a través de la cola. La función de ADD es guardar todos los objetos que aún no han finalizado el método y llamarlo al final System.shutdown . Configúrelo a través Runtime#runFinalizersOnExit .
Referencequeue
Esta cola de referencia se colocará en esta cola antes de que los objetos internos del objeto de referencia correspondiente se reciclarán (la descripción detallada se explicará en otro artículo sobre referencia), porque solo el objeto correspondiente debe obtenerse de esta cola, entonces este objeto definitivamente está listo para ser reciclado.
Luego llame al método finalizado correspondiente antes del reciclaje.
Hilo de finalización final
Este hilo sigue obteniendo datos de la cola, y luego llama al método finalizado correspondiente. El código correspondiente es el siguiente:
para (;;) {try {finalizador f = (finalizador) queue.remove (); F.RunFinalizer (JLA); } capt (interruptedException x) {// ignorar y continuar}}El finalizador de rubor correspondiente es el siguiente:
sincronizado (this) {if (hasBeenFinalized ()) return; remove ();} try {Object finalize = this.get (); if (finalizee! = null &&! (finalizee instancia de java.lang.enum)) {JLA.InvoKeFinalize (finalizee); / * La ranura de pila clara que contiene esta variable, para disminuir las posibilidades de retención falsa con un conservador GC */ finalizee = null; }} catch (showable x) {} super.clear ();En la lógica anterior, primero la llame, retírela y retírela de la finalización. Este método es garantizar que la finalización de cada objeto solo se llame una vez como máximo, es decir, se completa la llamada actual. Se registrará en el estado correspondiente, es decir, los retornos de Finalizados de Hasbeen verdadero (de hecho, significa apuntar el siguiente puntero en sí mismo. Es decir, nunca se ha finalizado, y no hay necesidad de llamar a la finalización de la finalización).
Lo siguiente es llamar al método finalizado correspondiente. jla.invokeFinalize anterior es en realidad llamar al método finalizar del objeto correspondiente. En este proceso, el objeto original se obtiene primero a través de Get. En todo el proceso JVM, la referencia no se establece en NULL antes de reciclar para FinalizeReference. Porque aquí, el objeto de referencia correspondiente siempre se puede obtener.
Después del procesamiento, el claro correspondiente finalmente se llama para borrar la referencia correspondiente. Esto logra el efecto de la referencia final que no tiene otro objeto para referencia.
En el procesamiento anterior, no hay límite en el tiempo de finalizar las llamadas. Por lo tanto, una vez que la finalización de un objeto se llame lentamente, afectará la ejecución de toda la cadena de reciclaje, y se generará una excepción de OOM correspondiente. Por lo tanto, a menos que en casos especiales, no reescribe finalice. Debe haber otros métodos para manejar los escenarios correspondientes. Por ejemplo, FinalizableReference en Guava.
Finalizador comienza el hilo
En el hilo anterior, se iniciará durante el inicio del proceso correspondiente. Se puede entender que el objeto desencadena la inicialización de la clase finalizador llamando register(object) . Luego, en el bloque de inicialización estática, se iniciará el hilo de reciclaje correspondiente. El código de inicialización correspondiente es el siguiente:
static {ThreadGroup tg = Thread.CurrentThread (). GetThreadGroup (); para (ThreadGroup tgn = tg; tgn! = null; tg = tgn, tgn = tg.getParent ()); Hilo finalizador = new FinnizerThread (TG); finalizador.setPriority (thread.max_priority - 2); finalizador.setdaemon (verdadero); Finalizer.start ();}La estática anterior es un bloque de inicialización estática, es decir, siempre que se use el finalizador de la clase, se activará la llamada correspondiente. El grupo de subprocesos utilizado aquí es un grupo de subprocesos del sistema, y la prioridad aún es relativamente alta, y está configurado como un hilo de fondo.
Cuando se usa jstack para imprimir hilos, los hilos que se muestran debajo de la figura aparecen aquí. Como se muestra en la figura a continuación
Resumir
Todo el finalizador trabaja en conjunto a través de FinalReference por el JVM y las clases Java correspondientes. No todo es implementado por JVM, por lo que se puede considerar que no es demasiado subyacente, sino implementar la semántica correspondiente. Todo es hecho por Java normal y cooperado por JVM. Comprender todo el proceso también es una comprensión del mecanismo de ejecución de Java en sí.