2010-01-20 29 views
9

Quando si utilizza una classe interna anonima come PropertyChangeListener a quale punto del ciclo di vita dell'oggetto è raccolta la garbageella di classe? Dopo che la classe contenente (SettingsNode) è stata recuperata? Devo rimuovere esplicitamente PropertyChangeListener nel finalizzatore della classe contenente (SettingsNode)?Java - Ciclo di vita della classe interna anonima

public class SettingsNode extends AbstractNode 
{ 
    public SettingsNode(Project project, ProjectSettings projectSettings) 
     throws IntrospectionException 
    { 
     // use an anonymous inner class to listen for changes 
     projectSettings.addPropertyChangeListener(ProjectSettings.PROP_NAME, 
      new PropertyChangeListener() 
      { 
       @Override 
       public void propertyChange(PropertyChangeEvent evt) 
       { 
        // handle event 
       } 
      }); 
    } 
} 
+0

In base alle risposte fornite, un anonimo non sembra essere l'opzione migliore per questo caso d'uso. Ora sto pensando che un'istanza delle classi interne sia probabilmente un'opzione migliore, dal momento che posso tenere un riferimento e chiamare un metodo removePropertyListener in futuro. – javacavaj

risposta

7

Come tutti gli oggetti, la classe interna anonima è idonea per la garbage collection quando l'ultimo riferimento ad esso non fa più riferimento a esso. Sto usando parole weasel qui perché Java non garantisce che le cose saranno GC – l'unica garanzia è che non accadrà finché c'è un riferimento.

In questo caso particolare, lo sarebbe quando projectSettings fa uno removePropertyListener() o è esso stesso garbage collection.

Perché projectSettings fa riferimento alla classe interna anonima e poiché la classe interna fa riferimento alla sua classe contenente, ciò significa che la classe contenente vivrà almeno fino a quando la classe interna.

+0

Anche se Java non garantisce * quando * qualcosa sarà GC, penso che devi dire che garantisce che qualcosa * sarà * GC'd se l'alternativa è un OutOfMemoryError. – Yishai

+0

Ora che l'hai detto non ne ho più :) Ovviamente hai ragione, e grazie; ma spero che nessuno dei nostri lettori scriva codice che dipende da questo comportamento. –

2

Si sta aggiungendo la classe PropertyChangeListener che si sta creando nell'oggetto projectSettings. Quel PropertyChangeListener non verrà raccolto fintanto che projectSettings lo fa riferimento.

2

Nell'esempio è stato mostrato che sia il nodo delle impostazioni che l'ascoltatore non possono essere recuperati fino a quando non vengono recuperate le impostazioni del progetto.

Sarà necessario rimuovere esplicitamente l'ascoltatore, ma probabilmente dovresti cercare un punto più affidabile di un finalizzatore.

SettingsNode non verrà recuperato fino a dopo la rimozione di PropertyChangeListener. Usando classi anonime per gli ascoltatori, è una causa comune di perdite di memoria.

EDIT follwing domanda da Alex B:

Se ProjectSettings esiste per la vita della domanda non è possibile rimuovere l'ascoltatore anonimo come non si dispone di un riferimento ad essa dopo che è stato registrato. Man mano che vengono create più istanze di SettingsNode, questi aggiungeranno i loro listener nel costruttore ma non verranno mai rimossi poiché nessun altro ha un riferimento a questi. Ciò interromperà quindi la rimozione di SettingsNodes e gli ascoltatori avranno riferimenti a SettingsNodes

+0

@Aaron: Puoi fare un esempio dove ci sarebbe una perdita di memoria? –

+0

@Alex: il codice nella domanda in realtà è già un esempio di perdita di memoria se non rimuove il listener quando 'SettingsNode' non è più necessario. Vedi la risposta di Carl spiega che questo succede. – x4u

0

Uno scenario tipico per perdita di memoria. Non consigliamo di finalizzare, in quanto potrebbe ritardare GC. Potresti esporre una funzione di ripulitura o ignorare dispose e annullare la registrazione.

Davvero sorpreso del fatto che lo swing non abbia una registrazione debilitata dell'ascoltatore. Probabilmente potresti provare qualche open source nella fucina sorgente?

1

Questa domanda è abbastanza datata.

Tuttavia, non sono d'accordo con la maggior parte delle risposte qui.

Non è necessario rimuovere esplicitamente l'ascoltatore. In questo caso, l'oggetto PropertyChangeListener della classe interna verrà pubblicato finché l'istanza contenente SettingsNode non viene raccolta.

Non è possibile rimuovere l'oggetto PropertyChangeListener perché non è stato mantenuto alcun riferimento.

Mentre è vero che l'oggetto PropertyChangeListener fa riferimento al suo oggetto contenitore SettingsNode, ciò non impedisce che l'oggetto contenitore venga de-referenziato e garbage collection.

Una volta de-referenziato l'oggetto contenitore, tutti gli oggetti contenuti in SettingsNode diventano "isola di isolamento". Tutti saranno raccolti.

Problemi correlati