Java - Anonymous Inner Class Life Cycle
When using an anonymous inner class as a PropertyChangeListener at what point in the object life cycle is the class garbage collected? After the containing class (SettingsNode) is reclaimed? Should I explicitly remove the PropertyChangeListener in the finalizer of the containing class (SettingsNode)?
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
}
});
}
}
Like all objects, the anonymous inner class is eligible for garbage collected when the last reference to it no longer references it. I'm using weasel wording here because Java doesn't guarantee that things will be GC'd – the only guarantee is that it won't happen as long as there is a reference.
In this particular case, that would be when projectSettings
either does a removePropertyListener()
or is itself garbage collected.
Because projectSettings
references the anonymous inner class and because the inner class references its containing class, that means the containing class will also live at least as long as the inner class.
You are adding the PropertyChangeListener class you are creating to the projectSettings object. That PropertyChangeListener will not be collected as long as projectSettings references it.
In the example you have shown both the settings node and the listener cannot be reclaimed until project settings is reclaimed.
You will need to explicitly remove the listener but you should probably look for somewhere more reliable than a finalizer.
SettingsNode will not get reclaimed until after the PropertyChangeListener is removed. Using anonymous classes for listeners clike this an be a common cause of memory leaks.
EDIT follwing question from Alex B:
If projectSettings exists for the life of the application you cannot remove the anonymous listener as you do not have a reference to it after it is registered. As multiple SettingsNode instances are created they will add their listeners in the constructor but they will never be removed as nobody else has a reference to them. This will then stop the SettingsNodes from being removed as well as the listeners have references to the SettingsNodes
This question is quite dated.
However, I do not agree with most of the answers here.
There is NO need to remove the listener explicitly. In this case, the inner class PropertyChangeListener object will live until the containing instance SettingsNode is garbaged collected.
You cannot actually remove the PropertyChangeListener object because there is no reference kept for it.
While it is true that the PropertyChangeListener object references its containing object SettingsNode, that does not prevent the containing object from being de-referenced and garbage collected.
Once the containing object is being de-referenced, all the objects contained by SettingsNode becomes an "island of isolation". All of them will be garbage collected.
A typical scenario for memory leak. Would not recommend finalize, as it could delay GC.You could expose a clean up function or override dispose and un-register.
Really surprised why swing does not have built in weak listener registration. Probably you could try some open source in source forge?
精彩评论