L'utilisation de références faibles est quelque chose dont je n'ai jamais vu la mise en œuvre. J'essaie donc de comprendre quel est le cas d'utilisation et comment fonctionnerait la mise en œuvre. Quand avez-vous eu besoin d'utiliser WeakHashMap
ou WeakReference
et comment a-t-il été utilisé?
Un problème avec les références fortes est la mise en cache, en particulier avec les très grandes structures telles que les images. Supposons que vous ayez une application devant utiliser des images fournies par l'utilisateur, comme l'outil de conception de site Web sur lequel je travaille. Naturellement, vous souhaitez mettre en cache ces images, car leur chargement à partir du disque est très coûteux et vous voulez éviter la possibilité d'avoir deux copies de l'image (potentiellement gigantesque) en mémoire à la fois.
Parce qu'un cache d'image est censé nous empêcher de recharger des images lorsque nous n'en avons pas absolument besoin, vous vous rendrez vite compte que le cache doit toujours contenir une référence à une image déjà en mémoire. Avec des références fortes ordinaires, cependant, cette référence elle-même forcera l'image à rester en mémoire, ce qui vous obligera à déterminer quand l'image n'est plus nécessaire en mémoire et à la supprimer du cache afin qu'elle devienne éligible pour le garbage collection. Vous devez dupliquer le comportement du ramasse-miettes et déterminer manuellement si un objet doit être en mémoire ou non.
Comprendre les références faibles , Ethan Nicholas
Une différence à clarifier est la différence entre un WeakReference
et un SoftReference
.
Fondamentalement, un WeakReference
sera GC-d par la JVM avec impatience, une fois que l'objet référencé ne comportera plus aucune référence dure . En revanche, un objet SoftReference
d aura tendance à être laissé en place par le ramasse-miettes jusqu'à ce qu'il ait réellement besoin de récupérer de la mémoire.
Un cache dans lequel les valeurs sont contenues dans WeakReference
s serait plutôt inutile (dans un WeakHashMap
, ce sont les clés faiblement référencées). SoftReferences
sont utiles pour encapsuler les valeurs lorsque vous souhaitez implémenter un cache qui peut augmenter et diminuer avec la mémoire disponible
Une utilisation courante de WeakReference
s et de WeakHashMap
s est en particulier d'ajouter des propriétés à des objets. Parfois, vous souhaitez ajouter des fonctionnalités ou des données à un objet, mais la sous-classification et/ou la composition ne sont pas une option. Dans ce cas, il est évident que vous devez créer une table de hachage reliant l'objet que vous souhaitez étendre à la propriété que vous souhaitez ajouter. . ensuite, chaque fois que vous avez besoin de la propriété, vous pouvez simplement la rechercher sur la carte. Toutefois, si les objets auxquels vous ajoutez des propriétés ont tendance à être détruits et à être beaucoup créés, vous pouvez vous retrouver avec de nombreux objets anciens dans votre carte occupant beaucoup de mémoire.
Si vous utilisez plutôt WeakHashMap
, les objets quitteront votre carte dès qu'ils ne seront plus utilisés par le reste de votre programme, ce qui correspond au comportement souhaité.
Je devais le faire pour ajouter des données à Java.awt.Component
Pour contourner un changement dans le JRE entre 1.4.2 et 1.5, j'aurais pu le corriger en sous-classant chaque composant qui m'intéressait int (JButton
, JFrame
, JPanel
....) mais c'était beaucoup plus facile avec beaucoup moins de code.
Un autre cas utile pour WeakHashMap
et WeakReference
est un implémentation du registre d'écoute.
Lorsque vous créez quelque chose qui veut écouter certains événements, vous enregistrez généralement un écouteur, par exemple.
manager.registerListener(myListenerImpl);
Si le manager
enregistre votre écouteur avec un WeakReference
, cela signifie que vous n'avez pas besoin de supprimer le registre, par exemple. avec une manager.removeListener(myListenerImpl)
car elle sera automatiquement supprimée une fois que votre auditeur ou votre composant détenant l'écouteur devient indisponible.
Bien sûr, vous pouvez toujours supprimer manuellement votre auditeur, mais si vous ne l'oubliez pas ou non, cela ne provoquera pas de fuite de mémoire, et cela n'empêchera pas votre auditeur d'être nettoyé.
Où WeakHashMap
entre-t-il dans l'image?
Le registre d'écoute qui souhaite stocker les écouteurs enregistrés sous le nom WeakReference
s a besoin d'une collection pour stocker ces références. Il n'y a pas de WeakHashSet
implémentation dans la bibliothèque standard Java seulement un WeakHashMap
, mais on peut facilement utiliser cette dernière pour "implémenter" la fonctionnalité de la première :
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
Avec ce listenerSet
pour enregistrer un nouvel écouteur, il vous suffit de l'ajouter à l'ensemble. Même s'il n'est pas supprimé explicitement, si l'écouteur n'est plus référencé, il sera automatiquement supprimé par la JVM.
Cet article de blog illustre l'utilisation des deux classes: Java: synchronisation sur un ID . L'utilisation va quelque chose comme ça:
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider fournit des objets basés sur l'id sur lesquels se synchroniser. Les exigences sont:
Ceci est réalisé en utilisant une carte de stockage interne de type:
WeakHashMap<Mutex, WeakReference<Mutex>>
L'objet est à la fois clé et valeur. Lorsque rien de l'extérieur de la carte ne fait référence à l'objet, vous pouvez le récupérer. Les valeurs de la carte sont stockées avec des références exactes. Par conséquent, elles doivent être entourées d'un WeakReference afin d'éviter une fuite de mémoire. Ce dernier point est couvert dans le javadoc .
Si vous voulez par exemple garder une trace de tous les objets créés d'une certaine classe. Pour toujours permettre à ces objets d'être ramassés, vous gardez une liste/carte de références faibles aux objets au lieu des objets eux-mêmes.
Maintenant, si quelqu'un pouvait m'expliquer des références fantômes, je serais heureux ...
Comme indiqué ci-dessus, les références faibles sont conservées tant qu'il existe une référence forte.
Un exemple d'utilisation serait d'utiliser WeakReference dans les écouteurs, de sorte que ceux-ci ne soient plus actifs une fois que la référence principale à leur objet cible aura disparu. Notez que cela ne signifie pas que le WeakReference est supprimé de la liste des écouteurs, un nettoyage est toujours nécessaire mais peut être effectué, par exemple, à des heures programmées. Cela a également pour effet d'empêcher l'objet écouté de conserver des références fortes et d'être éventuellement une source de mémoire saturée. Exemple: composants d'interface graphique Swing faisant référence à un modèle ayant un cycle de vie plus long que la fenêtre.
Tout en jouant avec les auditeurs comme décrit ci-dessus, nous avons rapidement compris que les objets étaient collectés "immédiatement" du point de vue de l'utilisateur.
J'ai fait une recherche de code de Google pour "new WeakHashMap ()".
J'ai eu un tas de correspondances du projet GNU classpath et