2010-05-18 5 views
18

Effective Java dit:Comment éviter les fuites de mémoire dans le rappel?

Une troisième source commune de fuites de mémoire est auditeurs et autres callbacks. Si vous implémentez une API où les clients enregistrent les rappels mais ne les les désinscrivent explicitement, ils vont s'accumuler sauf si vous prenez une action . La meilleure façon de s'assurer que les rappels sont ramassés rapidement est de ne stocker que de faibles références , par exemple, par en les stockant uniquement comme clés dans un WeakHashMap.

Je suis un débutant en Java. Quelqu'un pourrait-il m'apprendre comment créer des références faibles dans les rappels et me dire comment ils résolvent les problèmes de fuite de mémoire? Merci.

Répondre

11

Lire l'article this

Les aways clés de prendre sont les suivantes:

Vous pouvez penser que des références directes fortes références qui ne nécessitent pas de codage supplémentaire pour créer ou accéder à l'objet . Les trois autres types de références sont des sous-classes de la classe Reference contenue dans le package java.lang.ref. Les références logicielles sont fournies par la classe SoftReference , les références faibles par la classe WeakReference et les références fantômes par PhantomReference.

Les références logicielles agissent comme un cache de données. Lorsque la mémoire système est faible, le collecteur d'ordures peut libérer arbitrairement un objet dont la seule référence est une référence souple. En d'autres termes, s'il n'y a aucune référence forte à un objet, , cet objet est un candidat pour la version . Le garbage collector est requis pour libérer toutes les références douces avant de lancer une exception OutOfMemoryException . Les références faibles sont plus faibles que les références faibles. Si les seules références à un objet sont des références faibles, le garbage collector peut récupérer la mémoire utilisée par un objet à tout moment. Il n'y a aucune exigence pour une situation de mémoire faible . Généralement, la mémoire utilisée par l'objet est récupérée dans la prochaine passe du garbage collector.

Les références fantômes se rapportent aux tâches de nettoyage . Ils offrent une notification immédiatement avant que le collecteur de déchets effectue le processus de finalisation et libère un objet. Considérons c'est un moyen de faire des tâches de nettoyage au sein d'un objet .

suivi de la liste WeakListModel que je ne publierai pas pour éviter d'encombrer cette réponse.

+0

Je voudrais simplement noter que le lien est rompu – Maurice

+0

fixe, merci pour le point cela. –

+1

Wow flamboyant rapidement! merci – Maurice

8

Pour illustrer le concept avec un exemple rapide (brut), tenez compte des éléments suivants:

public interface ChangeHandler { 
    public void handleChange(); 
} 

public class FileMonitor { 

    private File file; 
    private Set<ChangeHandler> handlers = new HashSet<ChangeHandler>(); 

    public FileMonitor(File file) { 
     this.file = file; 
    } 

    public void registerChangeHandler(ChangeHandler handler) { 
     this.handlers.add(handler); 
    } 

    public void unregisterChangeHandler(ChangeHandler handler) { 
     this.handlers.remove(handler); 
    } 

    ... 
} 

Si une classe client utilise alors cette API FileMonitor, ils pourraient le faire:

public class MyClass { 

    File myFile = new File(...); 
      FileMonitor monitor = new FileMonitor(myFile); 

    public void something() { 
     ... 
     ChangeHandler myHandler = getChangeHandler(); 
     monitor.registerChangeHandler(myHandler); 
     ... 
    } 
} 

Si l'auteur du MyClass oublie alors d'appeler unregisterChangeHandler() quand c'est fait avec le gestionnaire, le FileMonitorHashSet référencera toujours l'instance qui a été enregistrée, l'amenant à rester en mémoire jusqu'au FileMonitor est détruit ou l'application se ferme. Pour éviter cela, Bloch suggère d'utiliser une collection de référence faible au lieu du HashSet, de sorte que si votre instance de MyClass est détruite, la référence sera supprimée de la collection du moniteur.

Vous pouvez remplacer le HashSet dans FileMonitor avec un WeakHashMap et utiliser les gestionnaires comme les clés, car celui-ci supprime automatiquement le gestionnaire de la collection lorsque sont partis toutes les autres références à l'objet.

+1

Merci pour l'exemple, mais je ne comprends toujours pas. Quand quelque chose() revient, la référence forte myHandler sera hors de portée. N'est-il pas vrai que le gestionnaire référencé par le WeakHashMap peut alors être détruit à tout moment (même si l'instance MyClass reste)? Ce n'est pas ce que tu veux? – kodu

+0

Ah, je commence à voir ... Vous pouvez utiliser WeakHashMap , alors la clé est en fait l'instance de MyClass. – kodu

+0

Je pense que myHandler devrait aller après quelque chose() revient, même si l'instance MyClass reste. donc WeakHashMap est meilleur que WeakHashMap yuxh

Questions connexes