web-dev-qa-db-fra.com

Comprendre les classes de référence de Java: SoftReference, WeakReference et PhantomReference

Quelqu'un peut-il expliquer la différence entre les trois classes de référence (ou poster un lien vers une explication de Nice)? SoftReference> WeakReference> PhantomReference, mais quand utiliserais-je chacun d'eux? Pourquoi y a-t-il une WeakHashMap mais pas SoftHashMap ou PhantomHashMap?

Et si j'utilise le code suivant ...

WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) {                 // ref can get collected at any time...
    System.gc();                   // Let's assume ref gets collected here.
    System.out.println(ref.get()); // Now what?!
}

...ce qui se produit? Dois-je vérifier si ref est nul avant chaque déclaration (c'est faux, mais que devrait je fais)? Désolé pour les questions à réponse rapide, mais j'ai du mal à comprendre ces classes Reference ... Merci!

78
Haywood Jablomey

La bibliothèque Java documentation du package Java.lang.ref caractérise la force décroissante des trois types de référence explicites.

Vous utilisez un SoftReference lorsque vous souhaitez que l'objet référencé reste en vie jusqu'à ce que le processus de l'hôte manque de mémoire. L'objet ne sera pas éligible à la collecte tant que le collecteur n'aura pas besoin de libérer de la mémoire. Lâchement déclaré, lier un SoftReference signifie: "Épinglez l'objet jusqu'à ce que vous ne puissiez plus."

En revanche, utilisez un WeakReference lorsque vous ne souhaitez pas influencer la durée de vie de l'objet référencé; vous voulez simplement faire une assertion séparée à propos de l'objet référencé, tant qu'il reste en vie. L'éligibilité de l'objet à la collecte n'est pas influencée par la présence de WeakReferences liés. Quelque chose comme un mappage externe d'une instance d'objet à une propriété associée, où la propriété doit uniquement être enregistrée tant que l'objet associé est en vie, est une bonne utilisation de WeakReferences et WeakHashMap.

Le dernier —PhantomReference— est plus difficile à caractériser. Comme WeakReference, un tel lien PhantomReference n'exerce aucune influence sur la durée de vie de l'objet référencé. Mais contrairement aux autres types de référence, on ne peut même pas déréférencer un PhantomReference. En un sens, cela ne pointe pas vers ce qui est indiqué, pour autant que les appelants puissent le savoir. Cela permet simplement d'associer des données liées à l'objet référencé - des données qui peuvent ensuite être inspectées et traitées lorsque le PhantomReference est mis en file d'attente dans son objet ReferenceQueue associé. Normalement, on dérive un type de PhantomReference et inclut des données supplémentaires dans ce type dérivé. Malheureusement, il y a un certain déclin à faire pour utiliser un tel type dérivé.

Dans votre exemple de code, ce n'est pas la référence ref (ou, si vous préférez, "variable") qui peut être null. C'est plutôt la valeur obtenue en appelant Reference#get() qui peut être null. Si cela s'avère nul, vous êtes trop tard; l'objet référencé est déjà sur le point d'être collecté:

final String val = ref.get();
if (null != val)
{
  // "val" is now pinned strongly.
}
else
{
  // "val" is already ready to be collected.
}
57
seh

Un lien: https://community.Oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMap ne fonctionnerait pas très bien car get renvoie toujours null pour les références fantômes.

Les caches sont difficiles, donc SoftHashMap pourrait ne pas fonctionner aussi bien que vous le pensez. Cependant, je pense que la bibliothèque de collections de Google contient une implémentation générale de la carte de référence.

Vous devriez toujours vérifier que get renvoie une variable non -null. (Notez que ne pas vérifier que la référence Reference elle-même n'est pas -null.) Dans le cas de chaînes internées, cela le sera toujours, mais (comme toujours) n'essayez pas d'être "intelligent" à ce sujet.

6

Il convient également de mentionner, comme indiqué dans le commentaire de Truong Xuan Tinh, ici: http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

Cette machine virtuelle Java de JRockit implémente les références faibles/douces/fantômes de manière différente de celle de Sun JVM.

3
James L
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;

if (ref != null) {                 
    System.gc(); 
    System.out.println(ref.get());
}

Dans ce cas, la sortie sera nulle. L'appel à System.gc() est important ici.

0
kopite