1. Type de référence (hors référence forte)
On peut comprendre que la sous-classe directe de référence est traitée par JVM, il n'a donc aucun effet pour hériter directement du type de référence dans le code. Il ne peut être hérité que de sa sous-classe. Les types de sous-classe correspondants incluent les éléments suivants. (Ignorez ceux qui ne sont pas utilisés en Java, comme Jnireference)
Perfectionnement
Référence faible
Référence finale
Fantôme
Le type de référence ci-dessus est également mentionné dans le Javadoc correspondant. FinalReference est spécialement conçu pour la méthode finalisée, et il existe plusieurs autres scénarios d'application spécifiques. Parmi eux, la softreference est utilisée dans les caches liées à la mémoire, la référence faible est utilisée dans la plupart des scénarios liés au recyclage. Phantomreference est utilisée dans les scénarios de rappel pour le recyclage des objets d'emballage (tels que la détection de fuite des ressources).
Vous pouvez visualiser directement les informations de sous-classe de plusieurs types dans l'IDE pour comprendre quels scénarios sont utilisés dans la plupart des cadres en héritant des types correspondants, afin que nous puissions réellement effectuer un traitement de sélection de type.
2. Constructeur de référence
Il fournit deux constructeurs en interne, l'un avec une file d'attente et l'autre sans file d'attente. La signification de la file d'attente est que nous pouvons surveiller cette file d'attente à l'extérieur. Autrement dit, si un objet est sur le point d'être recyclé, l'objet de référence correspondant sera placé dans cette file d'attente. Lorsque nous obtenons la référence, nous pouvons effectuer d'autres transactions.
Si vous ne le faites pas, vous ne pouvez entraîner que l'objet de référence en continu et juger si le grenage à l'intérieur revient nul (l'objet Phantomreference ne peut pas le faire, le GET renvoie toujours NULL, donc il n'a qu'un constructeur avec une file d'attente). Les deux méthodes ont des scénarios d'utilisation correspondants, selon l'application réelle. Par exemple, dans faiblehashmap, vous choisissez d'interroger les données de file d'attente pour déterminer si un objet sera recyclé. Pour ThreadLocalmap, il est utilisé pour déterminer si GET () est nul pour le traitement.
Le constructeur correspondant est le suivant:
Référence (t référence) {this (référent, null);} référence (t RÉFÉRENCE, REFEAGEQUE <? Super T> Direde) {this.referent = référent; this.queue = (file d'attente == null)? ReferenceQueue.null: file d'attente;}La file d'attente nulle ici peut être comprise comme une file d'attente qui ne nécessite aucun traitement des données dans sa file d'attente. Et il n'accédera à aucune donnée à l'intérieur.
Dans l'objet ci-dessus, la référence représente l'objet qu'il fait référence, c'est-à-dire l'objet dans lequel nous devons être enveloppés lorsque nous le construisons. La définition que l'objet est sur le point d'être recyclé signifie que cet objet n'a pas d'autre référence, sauf pour référence (non qu'il n'est pas vraiment référencé, mais l'accessibilité GCROOT est inaccessible pour éviter le problème de référence circulaire).
Une file d'attente est la file d'attente à notifier lorsque l'objet est recyclé. Lorsque l'objet est recyclé, l'objet de référence entier (pas l'objet recyclé) sera placé dans la file d'attente, puis les programmes externes peuvent obtenir les données correspondantes en surveillant cette file d'attente.
3. Référence et chaîne de référence de référence
La file d'attente ici est nominalement une file d'attente, mais il n'y a pas de structure de stockage réelle à l'intérieur. Son stockage dépend de la relation entre les nœuds internes. On peut comprendre que la file d'attente est une structure similaire à une liste liée, et le nœud ici est en fait la référence elle-même. On peut comprendre que la file d'attente est un conteneur pour une liste liée, qui stocke uniquement le nœud de tête actuel, et les nœuds suivants sont maintenus par chaque nœud de référence eux-mêmes via Suivant.
Valeur d'état de référence
Chaque objet de référence a une description d'état correspondante, c'est-à-dire qu'elle se décrit et l'objet emballé actuellement, pour la commodité de l'interrogation, du positionnement ou du traitement.
1. ACTIVE: état actif, c'est-à-dire que l'objet correspondant est un état de référence fort et n'a pas été recyclé. Dans cet état, l'objet ne sera pas placé dans la file d'attente. Dans cet état, NULL est NULL, et la file d'attente est la file d'attente référencée lorsqu'elle est définie.
2. En attente: Préparez-vous à le mettre dans la file d'attente. Dans cet état, les objets à traiter seront mis en file d'attente un par un dans la file d'attente. Au cours de cette fenêtre de temps, les objets correspondants sont à l'état en attente. Quelle que soit la référence, si vous entrez cet état, vous pouvez penser que dans l'état correspondant, ensuite est lui-même (défini par JVM), et la file d'attente est la file d'attente référencée lorsqu'elle est définie.
3. ENQUEUÉ: L'objet correspondant doit déjà être recyclé et l'objet de référence correspondant a été placé dans la file d'attente. Le thread externe est prêt à interroger la file d'attente pour obtenir les données correspondantes. Dans cet état, le suivant est le prochain objet à être traité, et la file d'attente est l'objet d'identification spécial en file d'attente.
4. Inactif: c'est-à-dire cet objet a été récupéré de la file d'attente de l'extérieur et a été traité. Cela signifie que cet objet de référence peut être recyclé et que l'objet encapsulé en interne peut également être recyclé (l'opération de recyclage réelle dépend de l'appel de l'action claire). On peut comprendre que ceux qui entrent dans cet état doivent être recyclés.
JVM n'a pas besoin de définir la valeur de l'état pour déterminer dans quel état se trouve la référence correspondante. Il n'a besoin que de calculer suivant et file d'attente pour porter des jugements.
4. ReferenceQueue # Head
Enregistrez toujours le dernier nœud à traiter dans la file d'attente actuelle. Vous pouvez considérer la file d'attente comme une file d'attente au premier tour. Lorsqu'un nouveau nœud entre, la logique suivante est adoptée.
newe.next = head; head = newe;
Ensuite, lors de l'obtention, utilisez la logique correspondante
tmp = head; head = tmp.next; return tmp;
V. Référence # Suivant
Autrement dit, décrire le nœud suivant stocké par le nœud de référence qui est sur le point d'être traité. Mais le prochain ne sera logique que lorsqu'il est placé dans la file d'attente. Afin de décrire la valeur d'état correspondante, après avoir été placée dans la file d'attente, sa file d'attente ne fera plus référence à la file d'attente. Au lieu de cela, il fera référence à une enjolive spéciale. Parce qu'il a été placé dans la file d'attente, il ne sera plus placé dans la file d'attente.
6. Référence # référent
C'est-à-dire décrire l'objet réel référencé par la référence actuelle, qui sera traité soigneusement comme indiqué dans l'annotation. Autrement dit, lorsque cette chose sera recyclée, et si elle est recyclée, elle sera directement définie sur NULL, et les programmes externes peuvent apprendre de l'objet de référence lui-même (plutôt que référent) que le comportement de recyclage se produit.
7. ReferenceQueue # ENQUEUe en attente de référence en attente
Ce processus est le processus de l'objet de référence de actif-> en attente Cette méthode consiste à traiter l'objet qui gère l'état en attente en tant qu'état entendu. Le processus correspondant est la logique précédente, c'est-à-dire qu'un nœud est étonné et le code correspondant est le suivant.
R.Queue = EnqueUeUe; R.Next = (Head == NULL)? R: Head; Head = R; queuelngth ++; Lock.NotifyAll ();
Le dernier Nitify signifie notifier le programme externe qui bloque dans la file d'attente actuelle auparavant. (C'est-à-dire que l'objet en attente n'a pas été obtenu auparavant)
8. Référence # tryhandleprend
C'est-à-dire qu'il gère le changement de l'objet de référence de l'état actif à l'état en attente. À l'intérieur de l'objet de référence, il existe un champ statique et sa déclaration correspondante est la suivante:
/ * Liste des références attendant d'être en cours. Le collectionneur ajoute * des références à cette liste, tandis que le thread de manche de référence les supprime *. Cette liste est protégée par l'objet de verrouillage ci-dessus. La liste * utilise le champ découvert pour relier ses éléments. * / référence statique privée <objet> en attente = null;
On peut comprendre que JVM mettra l'objet à traiter sur ce champ statique lorsque GC. Dans le même temps, un autre champ découvert représente l'objet suivant de l'objet à traiter. Autrement dit, on peut comprendre que l'objet à traiter est également une liste liée. Il est en file d'attente par la découverte. Il vous suffit de continuer à devenir en attente, puis d'obtenir en continu l'objet suivant via la découverte. Étant donné que les deux threads peuvent accéder à cet objet en attente, il est nécessaire d'utiliser le traitement de verrouillage.
Le processus de traitement correspondant est le suivant:
if (en attente! = null) {r = en attente; // 'instanceof' pourrait jeter OutOfMemoryError parfois // alors faites-le avant de ne pas lier 'r' de la chaîne 'en attente' ... C = r instance de nettoyant? (Nettoyant) R: NULL; // dissocier «r» de la chaîne «en attente» en attente = r. découverte; R.Discovered = NULL;} // ENQUEUe l'objet de traitement, c'est-à-dire qu'il entre dans la référence de l'état entendu <? super objet> q = r.queue; if (q! = ReferenceQueue.null) q.enqueue (r);9. Référence # Clear
Effacer l'objet d'origine référencé par l'objet de référence, afin que l'objet d'origine ne puisse plus être accessible via la méthode get (). À partir de l'idée de conception correspondante, car il a entré l'objet de file d'attente, cela signifie que l'objet correspondant doit être recyclé car il n'est pas nécessaire d'accéder à nouveau à l'objet d'origine. Cette méthode ne sera pas appelée par le JVM, et JVM efface directement la référence correspondante à travers les opérations de champ, et son implémentation spécifique est cohérente avec la méthode actuelle.
La sémantique de Clear est de null la référence.
Une fois que l'objet FaibleReference entre dans la file d'attente, la référence correspondante est nul.
Objet SoftReference, si l'objet n'entre pas dans la file d'attente lorsque la mémoire est suffisante, la référence correspondante ne sera pas nul. S'il doit être traité (pas assez de mémoire ou d'autres politiques), la référence correspondante est définie sur NULL, puis entrez la file d'attente.
Objet FinalReference, car il doit appeler son objet Finalize, même si sa référence est entrée dans une file d'attente, sa référence ne sera pas nul, c'est-à-dire qu'elle ne sera pas effacée.
L'objet Phantomreference, car le GET lui-même est implémenté pour renvoyer NULL, n'est pas très utile. Parce qu'il ne sera pas effacé, qu'il s'agisse ou non de l'observation.
10. Fil d'enquare de référence
Comme mentionné ci-dessus, JVM définira l'objet à traiter dans l'objet en attente, il doit donc y avoir un thread pour effectuer des opérations d'agitation continues. Ce fil fait référence au fil du processeur, et sa priorité est max_priority, c'est-à-dire la plus élevée. Le processus de démarrage correspondant est créé d'initialisation statique, qui peut être comprise comme lorsqu'un objet ou une classe de référence est utilisé, ce fil sera créé et démarré. Le code correspondant est le suivant:
statique {threadGroup tg = thread.currentThread (). getThreadGroup (); pour (ThreadGroup tgn = tg; tgn! = null; tg = tgn, tgn = tg.getParent ()); Thread Handler = new ReferenceHandler (TG, "Reference Handler"); / * S'il y avait une priorité spéciale uniquement au système supérieur à * max_priority, elle serait utilisée ici * / handler.setPriority (thread.max_priority); handler.setDaemon (true); handler.start ();}Sa priorité est la plus élevée, qui peut être comprise comme la nécessité de traiter en continu des objets de référence. Lors de l'impression d'un fil en cours d'exécution via JSTACK, le gestionnaire de référence correspondant fait référence au thread initialisé ici, comme indiqué ci-dessous:
11. JVM lié
Dans chacun des points de traitement ci-dessus, ils sont liés au processus de recyclage JVM. Autrement dit, on pense que le processus GC fonctionnera en conjonction avec la référence correspondante. Par exemple, en utilisant le collecteur CMS, le processus prélean est impliqué dans l'ensemble du processus mentionné ci-dessus, et le traitement des remarques de la Softreference, etc. En même temps, divers traitements de l'objet de référence doivent également être liés au type spécifique. Le traitement JVM correspondant utilise le code C ++, il doit donc être soigneusement réglé.
12. Résumé
Comme l'objet FinalReference, l'intégralité de la référence et de la référence est un groupe de groupes de traitement qui fonctionnent ensemble. Afin d'assurer différentes sémantiques de référence, le processus lié à JVM GC est finalement réalisé pour différents scénarios et différents niveaux de référence.
De plus, car l'utilisation directe de référence et les threads d'ouverture pour surveiller les files d'attente est trop gênante et compliquée. Vous pouvez vous référer à FinalizableReferenceeue implémenté par Google Guava et à l'objet FinaliSableReference correspondant. Le processus de traitement peut être un peu simplifié. Ce qui précède est l'intégralité du contenu de cet article, et j'espère que cela apportera une aide à l'apprentissage ou au travail de chacun.