Question Quelle est la différence entre SoftReference et WeakReference en Java?


Quelle est la différence?


686
2017-11-18 18:26


origine


Réponses:


De Comprendre les références faibles, par Ethan Nicholas:

Références faibles

UNE référence faible, simplement, est un   référence qui n'est pas assez forte pour   forcer un objet à rester en mémoire.   Les références faibles vous permettent de tirer parti   la capacité de l'éboueur à   déterminer l'accessibilité pour vous, de sorte que vous   ne pas avoir à le faire vous-même. Toi   créer une référence faible comme ceci:

WeakReference weakWidget = new WeakReference(widget);

et alors   ailleurs dans le code, vous pouvez utiliser    weakWidget.get() pour obtenir le réel    Widget objet. Bien sûr, le faible   la référence n'est pas assez forte pour   empêcher la collecte des ordures, de sorte que vous pouvez   trouver (s'il n'y a pas de forte   références au widget)    weakWidget.get() commence soudainement   retour null.

...

Références douces

UNE référence souple est exactement comme un   référence faible, sauf qu'il est moins   désireux de jeter l'objet à   auquel il se réfère. Un objet qui est   seulement faiblement accessible (le plus fort   les références à celui-ci sont WeakReferences)   sera jeté à la prochaine poubelle   cycle de collecte, mais un objet   est doucement accessible généralement   restez pour un moment.

SoftReferences ne sont pas Champs obligatoires à   se comporter différemment de    WeakReferences, mais en pratique doucement   objets accessibles sont généralement   conservé aussi longtemps que la mémoire est en   offre abondante. Cela les rend un   excellente base pour un cache, tel   comme le cache d'image décrit ci-dessus,   puisque vous pouvez laisser les ordures   collecteur s'inquiéter à la fois comment   joignable les objets sont (fortement   objet accessible sera jamais être retiré   de la cache) et à quel point il a besoin   la mémoire qu'ils consomment.

Et Peter Kessler ajouté dans un commentaire:

Sun JRE traite les SoftReferences différemment des WeakReferences. Nous essayons de conserver l'objet référencé par un SoftReference s'il n'y a pas de pression sur la mémoire disponible. Un détail: la stratégie pour les JRE "-client" et "-server" est différente: le JRE -client essaie de réduire votre empreinte en préférant effacer les SoftReferences plutôt que d'étendre le tas, tandis que le JRE -serveur essaie de garder votre performances élevées en préférant augmenter le tas (si possible) plutôt que d'effacer SoftReferences. Une taille unique ne convient pas à tous.


810
2017-11-18 18:37



Les références faibles sont recueillies avec empressement. Si GC trouve qu'un objet est faiblement accessible (accessible uniquement par des références faibles), il faibles références à cet objet immédiatement. En tant que tels, ils sont bons pour garder une référence à un objet pour lequel votre programme garde également (fortement référencé) "information associée" somewere, comme caché des informations de réflexion sur une classe, ou un wrapper pour un objet, etc. Tout ce qui n'a pas de sens à conserver après l'objet auquel il est associé avec est GC-ed. Lorsque la référence faible est effacée, il est mis en file d'attente dans un la file d'attente de référence que votre code interroge quelque part, et il rejette la objets associés ainsi. Autrement dit, vous gardez des informations supplémentaires sur un objet, mais cette information n'est pas nécessaire une fois que l'objet auquel il se réfère s'en va. En fait, dans certaines situations, vous pouvez même sous-classer WeakReference et conservez les informations supplémentaires associées à l'objet dans les champs de la sous-classe WeakReference. Une autre utilisation typique de WeakReference est en conjonction avec Maps pour conserver les instances canoniques.

D'autre part, les SoftReferences permettent de mettre en cache des ressources externes et recréables. car le GC tarde généralement à les effacer. Il est garanti que tous Les SoftReferences seront effacées avant que OutOfMemoryError ne soit lancé, ils théoriquement ne peut pas provoquer un OOME [*].

Exemple de cas d'utilisation typique: conserver une forme analysée d'un contenu d'un fichier. Vous implémenteriez un système dans lequel vous chargeriez un fichier, l'analyseriez et le conserveriez. un SoftReference à l'objet racine de la représentation analysée. La prochaine fois vous avez besoin du fichier, vous allez essayer de le récupérer via le SoftReference. Si vous pouvez le récupérer, vous vous êtes épargné une autre charge / analyse, et si le GC l'a effacé en attendant, vous le rechargez. De cette façon, vous utilisez gratuitement mémoire pour l'optimisation des performances, mais ne risquez pas un OOME.

Maintenant pour le [*]. Garder un SoftReference ne peut pas causer un OOME en soi. Si d'autre part, vous utilisez par erreur SoftReference pour une tâche que WeakReference veut dire à utiliser (à savoir, vous gardez en quelque sorte les informations associées à un objet fortement référencé, et le rejeter lorsque l'objet de référence obtient effacé), vous pouvez exécuter OOME en tant que votre code qui interroge ReferenceQueue et rejette les objets associés peuvent arriver à ne pas courir dans un délai mode.

Donc, la décision dépend de l'utilisation - Si vous mettez en cache des informations coûteuses à construire, mais néanmoins reconstructible à partir d'autres données, utilisez des références souples - si vous gardez une référence à une instance canonique de certaines données, ou vous voulez avoir une référence à un objet sans "le posséder" (donc en l'empêchant d'être GC'd), utilisez une référence faible.


183
2017-11-18 18:27



En Java; ordre du plus fort au plus faible, il y a: fort, doux, faible et fantôme

UNE Une référence solide est une référence normale qui protège l'objet référencé de la collecte par GC. C'est-à-dire, ne jamais ramasser les ordures.

UNE Référence souple est éligible pour la collecte par garbage collector, mais ne sera probablement pas collecté tant que sa mémoire n'est pas nécessaire. c'est-à-dire que les ordures se rassemblent avant OutOfMemoryError.

UNE Référence faible est une référence qui ne protège pas un objet référencé de la collecte par GC. c'est-à-dire que les ordures se rassemblent lorsqu'aucune référence forte ou douce.

UNE Référence fantôme est une référence à un objet référencé de façon fantomatique après qu'il a été finalisé, mais avant que sa mémoire allouée ait été récupérée.

La source 

Analogie: Supposons qu'une JVM est un royaume, Object est un roi du royaume, et GC est un attaquant du royaume qui tente de tuer le roi (objet).

  • Quand le roi est Fort, GC ne peut pas le tuer.
  • Quand le roi est Doux, Le GC l'attaque mais le roi règne sur le royaume avec protection jusqu'à ce que des ressources soient disponibles.
  • Quand le roi est FaibleLe CG l'attaque mais dirige le royaume sans protection.
  • Quand le roi est Fantôme, GC l'a déjà tué mais le roi est disponible via son âme.

98
2017-08-03 10:39



Référence faible http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Principe:  weak reference est lié à la collecte des ordures. Normalement, objet ayant un ou plusieurs reference ne seront pas éligibles pour le ramassage des ordures.
Le principe ci-dessus n'est pas applicable lorsqu'il est weak reference. Si un objet n'a qu'une faible référence avec d'autres objets, il est prêt pour la récupération de place.

Regardons l'exemple ci-dessous: Nous avons un Map avec des objets où Key fait référence à un objet.

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

Maintenant, pendant l'exécution du programme, nous avons fait emp = null. le Map tenir la clé n'a pas de sens ici, car il est null. Dans la situation ci-dessus, l'objet n'est pas collecté.

WeakHashMap

WeakHashMap est celui où les entrées (key-to-value mappings) sera supprimé lorsqu'il ne sera plus possible de les récupérer Map.

Permettez-moi de montrer l'exemple ci-dessus même avec WeakHashMap

import java.util.WeakHashMap;

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

Sortie: A pris 20 calls to System.gc() pour aboutir à aMap size de: 0.

WeakHashMap n'a que de faibles références aux clés, pas de références fortes comme les autres Map Des classes. Il y a des situations que vous devez prendre en compte lorsque la valeur ou la clé est fortement référencée bien que vous ayez utilisé WeakHashMap. Cela peut être évité en enveloppant l'objet dans un WeakReference.

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

Références logicielles

Soft Reference est légèrement plus forte que la référence faible. La référence souple permet la récupération de place, mais supplie le garbage collector de l'effacer uniquement s'il n'y a pas d'autre option.

Le ramasse-miettes ne collecte pas de façon agressive les objets facilement accessibles comme il le fait avec ceux qui sont faiblement accessibles - il ne collecte que des objets facilement accessibles s'il a vraiment besoin de la mémoire. Les références souples sont une façon de dire au garbage collector: «Tant que la mémoire n'est pas trop serrée, je voudrais garder cet objet, mais si la mémoire devient très serrée, allez-y, récupérez-le et je traiterai avec ça." Le garbage collector est nécessaire pour effacer toutes les références souples avant de pouvoir lancer OutOfMemoryError.


67
2017-10-17 03:05



La seule vraie différence entre une référence douce et une référence faible est que le garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.


41
2018-04-03 15:23



SoftReference est conçu pour les caches. Quand il est constaté qu'un WeakReference fait référence à un objet autrement inaccessible, alors il sera effacé immédiatement. SoftReference peut être laissé tel quel. Typiquement, il existe un algorithme relatif à la quantité de mémoire libre et à la dernière heure utilisée pour déterminer si elle doit être effacée. L'algorithme actuel de Sun est d'effacer la référence si elle n'a pas été utilisée en autant de secondes qu'il y a de mégaoctets de mémoire libre sur le tas Java (configurable, le serveur HotSpot vérifie le tas maximum possible tel que défini par -Xmx). SoftReferences sera effacé avant OutOfMemoryError est jeté, sauf si autrement atteignable.


21
2017-11-18 18:27



La seule vraie différence

Par Le document, lâche WeakReferences doit être effacé par un GC en cours d'exécution.

Par Le document, Libérer SoftReferences doit être effacé avant que le MOO soit lancé.

C'est la seule vraie différence. Tout le reste ne fait pas partie du contrat. (Je suppose que les derniers documents sont contractuels.)

Les SoftReferences sont utiles. Les caches sensibles à la mémoire utilisent SoftReferences, pas WeakReferences.


Le seul correct L'utilisation de WeakReference consiste à observer l'exécution du GC. Vous faites cela en créant un nouveau WeakReference dont l'objet sort immédiatement de sa portée, puis essayez d'obtenir null à partir de weak_ref.get(). Quand il est null, vous apprenez que, entre cette durée, le GC a couru.

Pour ce qui est de Incorrect l'utilisation de WeakReference, la liste est infinie:

  • un piratage minable pour mettre en œuvre la priorité-2 sofreference de sorte que vous n'avez pas à en écrire un, encore il ne fonctionne pas comme prévu car le cache serait effacé chaque GC s'exécute, même s'il y a de la mémoire disponible. Voir https://stackoverflow.com/a/3243242/632951 pour les phails. (De plus, que faire si vous avez besoin de plus de 2 niveaux de priorité de cache? Vous auriez toujours besoin d'une vraie bibliothèque pour cela.)

  • un piratage pour associer des données à un objet d'une classe existante, encore il crée une fuite de mémoire (OutOfMemoryError) lorsque votre GC décide de faire une pause après la création de vos références faibles. D'ailleurs, c'est au-delà de laide: Une meilleure approche consiste à utiliser des tuples.

  • un piratage minable pour associer des données à un objet d'une classe existante, où la classe a le culot de se rendre non-sous-classifiable, et est utilisé dans un code de fonction existant que vous devez appeler. Dans ce cas, la solution appropriée consiste soit à éditer la classe et à la rendre sous-classifiable, soit à éditer la fonction et à lui faire prendre une interface au lieu d'une classe, ou à utiliser une autre fonction.


6
2017-09-19 03:08



Les six types d'états d'accessibilité des objets en Java -

  1. FortObjets facilement accessibles - GC ne sera pas recueillir (récupérer la mémoire occupée par) ce genre d'objets. Ceux-ci sont accessible via un nœud racine ou un autre objet fortement accessible  (c'est-à-dire via des variables locales, des variables de classe, des variables d'instance, etc.)
  2. DouxObjets facilement accessibles - GC peut tenter pour collecter ce genre d'objets en fonction de la contention de la mémoire. Ceux-ci sont accessibles depuis la racine via un ou plusieurs objets de référence souples
  3. FaibleObjets facilement accessibles - GC doit recueillir ce genre d'objets. Celles-ci sont accessibles depuis la racine via un ou plusieurs objets de référence faibles
  4. Ressusciter objets - GC est déjà en train de collecter ces objets. Mais ils peuvent retourner dans l'un des états - Fort / Doux / Faible par l'exécution de certains finaliseurs
  5. Fantômeobjet joignable - GC est déjà en train de collecter ces objets et a décidé de ne pas être ressuscité par un finaliseur (s'il déclare lui-même une méthode finalize (), alors son finalizer aura été exécuté). Ceux-ci sont accessibles depuis la racine via un ou plusieurs objets de référence fantômes
  6. Inaccessible object - Un objet n'est ni fortement, faiblement, faiblement, ni fantomatique, et n'est pas ressuscitable. Ces objets sont prêts pour la récupération

Pour plus de détails: https://www.artima.com/insidejvm/ed2/gc16.html " effondrer


3
2017-08-17 05:31



Référence faible

Lorsqu'il y a une ou plusieurs références à un objet, il ne sera pas collecté en Java. Mais cette règle dépend du type de référence. Si un objet n'a qu'une référence faible associée à d'autres objets, il s'agit d'un candidat valide pour la récupération de place.

Prenons un exemple de scénario pour mieux le comprendre. Laissez TextView être un objet (récemment programmé sous Android et donc en utilisant sa classe par exemple :-)) et nous aurons des identifiants générés par le programme pour son identification. Ces identifiants sont utilisés dans un autre objet pour référencer les TextViews.

...
Map textViewIdMap = new HashMap();
textViewIdMap.put(textView1, iD1);
textViewIdMap.put(textView2, iD2)
...


key est l'objet TextView et la valeur est l'Id. Maintenant, lors de l'exécution du programme, nous avons supprimé un objet TextView dit textView1. Nous n'avons pas besoin de cet objet de vue, donc nous l'avons rendu nul. Maintenant, qu'adviendra-t-il de la paire clé-valeur (textView1, iD1) stockée dans HashMap. Cette paire n'a pour l'instant aucun sens et elle n'est pas requise car cette vue de texte est elle-même nulle.

Donc, programmatique, nous devons nous assurer que, lorsqu'un textView est supprimé, son entrée correspondante dans la carte doit être supprimée. Seulement alors, cet objet devient un candidat pour la collecte des ordures. Sinon, même s'il n'est pas utilisé au moment de l'exécution, cet objet périmé ne sera pas récupéré.


Référence souple

 La référence douce est légèrement plus forte que la référence faible. La référence souple permet la récupération de place, mais supplie le garbage collector de l'effacer uniquement s'il n'y a pas d'autre option. C'est-à-dire qu'il est éligible pour la récupération de place, mais le garbage collector peut l'enlever en fonction de la surcharge de mémoire dont il dispose. S'il reste peu de mémoire et qu'il est en mesure de récupérer de la mémoire, il collecte les références logicielles.


1
2017-10-19 15:51