2010-01-20 177 views
9

在对象生命周期的哪个点使用匿名内部类作为PropertyChangeListener时,是否收集了类垃圾?包含类(SettingsNode)被回收后?我应该显式移除包含类(SettingsNode)的终结器中的PropertyChangeListener吗?Java - 匿名内部类生命周期

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

根据提供的答案,匿名似乎不是此用例的最佳选项。我现在认为一个实例内部类可能是一个更好的选择,因为我可以保存一个引用,并在将来的某个时刻调用removePropertyListener方法。 – javacavaj 2010-01-20 20:39:25

回答

7

像所有的对象,匿名内部类是符合垃圾收集时的最后一个引用不再引用它。我在这里使用黄鼠狼的措辞,因为Java不保证事情将会GC'd –唯一的保证是,只要有参考,它不会发生。

在这种特殊情况下,当projectSettings要么是removePropertyListener(),要么本身是垃圾收集。

因为projectSettings引用了匿名内部类,并且由于内部类引用了它的包含类,这意味着包含类也将至少与内部类一样长。

+0

尽管Java不保证*什么时候会GC'd,我认为你必须说它保证某些*将* GC'd如果替代是一个OutOfMemoryError。 – Yishai 2010-01-20 20:27:35

+0

现在你已经说过了,我不必再有了:)当然你是对的,谢谢你;但我希望我们的读者都不会写出依赖于此行为的代码。 – 2010-01-20 22:01:29

2

您正在将您正在创建的PropertyChangeListener类添加到projectSettings对象。只要projectSettings引用它,该PropertyChangeListener就不会被收集。

2

在示例中,您已经显示设置节点和侦听器都不能回收,直到项目设置被回收。

您将需要显式删除侦听器,但您应该寻找比终结器更可靠的地方。

直到PropertyChangeListener被移除后,SettingsNode才会被回收。听众使用匿名类会产生内存泄漏的常见原因。

编辑从亚历克斯·B follwing问题:

如果projectSettings存在因为你没有对它的引用在注册后无法删除匿名监听器的应用程序的生命。 由于创建了多个SettingsNode实例,因此它们将在构造函数中添加它们的侦听器,但它们将永远不会被删除,因为没有人拥有对它们的引用。然后这将停止SettingsNodes被删除以及听众对SettingsNode的引用

+0

@Aaron:你能否举一个例子说明会发生内存泄漏? – 2010-01-20 20:13:44

+0

@Alex:如果在不再需要'SettingsNode'时不删除监听器,那么问题中的代码实际上已经是内存泄漏的示例。看到卡尔的答案解释了这种情况。 – x4u 2010-01-20 20:22:38

0

内存泄漏的典型场景。不会推荐最终确定,因为它可能会延迟GC。您可能会公开清理功能或覆盖处理和取消注册。

真的很惊讶为什么swing没有建立在弱听者注册。可能你可以在source forge中尝试一些开源代码?

1

这个问题相当过时。

但是,我不同意这里的大多数答案。

没有必要明确地删除监听器。在这种情况下,内部类PropertyChangeListener对象将存活直到包含的实例SettingsNode被垃圾收集。

您实际上不能删除PropertyChangeListener对象,因为没有为它保留引用。

尽管PropertyChangeListener对象引用其包含的对象SettingsNode是对的,但并不妨碍包含对象被取消引用和垃圾回收。

一旦包含对象被取消引用,SettingsNode包含的所有对象就成为一个“隔离岛”。他们都将被垃圾收集。