Citation de référence finale
Cette classe est un type de package, indiquant qu'il n'est pas une partie publique et hérite de la référence, ce qui signifie qu'il s'agit également d'un type de référence spécifique. Par conséquent, avant que chaque objet enveloppé dedans ne soit recyclé, il sera placé dans la référence spécifiée.
Cet objet de référence est spécifiquement utilisé pour la classe avec des méthodes finalisées. On peut comprendre que chaque objet avec des méthodes correspondants sera encapsulé comme un objet FinalRefernece.
Étant donné que la méthode finalisée est définie par l'objet, son implémentation par défaut est vide. Ensuite, si cette méthode est réécrite, le corps de la méthode ne sera certainement pas vide. Cette différence peut être faite à travers cela. Tant que la méthode finalisée implémente une classe qui n'est pas vide, les objets générés doivent être enregistrés dans finalRefernece.
Cette étape peut être enregistrée en conséquence en appelant la méthode du constructeur par défaut de l'objet pendant NewInstance.
Finalizer # Méthode d'enregistrement
Lorsque cette méthode est principalement appelée, l'objet Finalizer correspondant sera généré et l'objet Finalizer est hérité de FinalReference. Cette méthode est déclarée comme suit:
/ * Invoqué par VM * / STATIC VOID Register (objet Finalizee) {New Finalize (Finalizee);} Comme on peut le voir à partir des commentaires ci-dessus, cette méthode sera appelée par JVM à une période spécifique.
Ensuite, passez au constructeur de Finalizer, comme indiqué ci-dessous:
Private Finalizer (objet Finalizee) {super (finizee, file d'attente); ajouter();} On peut voir que l'objet de référence correspondant sera rappelé via la file d'attente. La fonction d'ADD consiste à enregistrer tous les objets qui n'ont pas encore finalisé la méthode et l'appeler sur le System.shutdown final.shutdown. Définissez-le via Runtime#runFinalizersOnExit .
ReferenceQueue
Cette file d'attente de référence sera placée dans cette file d'attente avant que les objets internes de l'objet de référence correspondant ne soient recyclés (la description détaillée sera expliquée dans un autre article sur la référence.), Parce que seul l'objet correspondant doit être obtenu à partir de cette file d'attente, alors cet objet est définitivement prêt à être recyclé.
Appelez ensuite la méthode Finalize correspondante avant le recyclage.
Finalizethread Thread
Ce fil continue d'obtenir des données de la file d'attente, puis appelle la méthode Finalize correspondante. Le code correspondant est le suivant:
for (;;) {try {finalizer f = (finalizer) queue.reMove (); F.Runfinalizer (JLA); } catch (InterruptedException x) {// ignorer et continuer}}Le Runfinalizer correspondant est le suivant:
synchronisé (this) {if (hasbeEenfinalized ()) return; retire ();} try {object finalize = this.get (); if (finalizee! = null &&! (finizee instanceof java.lang.enum)) {jla.invokefinalize (finalizee); / * L'emplacement de pile transparent contenant cette variable, pour diminuer les chances de fausse rétention avec un gc * / finalizee conservateur = null; }} catch (Throwable X) {} super.clear ();Dans la logique ci-dessus, premier appel supprime et supprimez-le de la finalisation. Cette méthode consiste à s'assurer que la finalisation de chaque objet ne sera appelé qu'une seule fois, c'est-à-dire que l'appel actuel est terminé. Il sera enregistré dans l'état correspondant, c'est-à-dire que HasbeEenfinalized revient vrai (en fait, cela signifie pointer le prochain pointeur en lui-même.
Ensuite, c'est d'appeler la méthode Finalize correspondante. jla.invokeFinalize ci-dessus est en fait d'appeler la méthode finalisée de l'objet correspondant. Dans ce processus, l'objet d'origine est d'abord obtenu via GET. Dans l'ensemble du processus JVM, la référence n'est pas définie sur NULL avant le recyclage pour la finizizérence. Parce qu'ici, l'objet de référence correspondant peut toujours être obtenu.
Après traitement, le clair correspondant est finalement appelé pour effacer la référence correspondante. Cela réalise l'effet de la référence finale n'ayant aucun autre objet à référence.
Dans le traitement ci-dessus, il n'y a pas de limite sur le temps d'appel Finaliser. Par conséquent, une fois que la finalisation d'un objet est appelé lentement, elle affectera l'exécution de toute la chaîne de recyclage et une exception OOM correspondante sera générée. Par conséquent, à moins que, dans des cas particuliers, ne réécrivez pas finaliser. Il devrait y avoir d'autres méthodes pour gérer les scénarios correspondants. Par exemple, finizablereference dans la goyave.
Finalizer démarre le fil
Dans le fil ci-dessus, il sera démarré lors du démarrage du processus correspondant. On peut comprendre que l'objet déclenche l'initialisation de la classe Finalizer en appelant register(object) . Ensuite, dans le bloc d'initialisation statique, le fil de recyclage correspondant sera démarré. Le code d'initialisation correspondant est le suivant:
statique {threadGroup tg = thread.currentThread (). getThreadGroup (); pour (ThreadGroup tgn = tg; tgn! = null; tg = tgn, tgn = tg.getParent ()); Thread Finalizer = new FinalizerThread (TG); finalizer.setPriority (thread.max_priority - 2); finalizer.setDaemon (true); finalizer.start ();}Le statique ci-dessus est un bloc d'initialisation statique, c'est-à-dire tant que le finaliseur de classe est utilisé, l'appel correspondant sera déclenché. Le groupe de threads utilisé ici est un groupe de threads système, et la priorité est encore relativement élevée, et elle est configurée en tant que thread d'arrière-plan.
Lorsque vous utilisez JSTACK pour imprimer des threads, les fils illustrés sous la figure apparaissent ici. Comme indiqué dans la figure ci-dessous
Résumer
L'ensemble Finalizer travaille ensemble via FinalReference par le JVM et les classes Java correspondantes. Il n'est pas tout mis en œuvre par JVM, il peut donc être considéré qu'il n'est pas trop sous-jacent, mais pour implémenter la sémantique correspondante. Tout est fait par Java normal et coopéré par JVM. Comprendre l'ensemble du processus est également une compréhension du mécanisme de course de Java lui-même.