【问题标题】:How to implement explicit marking some reference as "unneeded" in Java?如何在 Java 中实现将某些引用显式标记为“不需要”?
【发布时间】:2014-12-01 16:57:10
【问题描述】:

在我看来,我发现了一种情况,标准的垃圾收集算法不能很好地使用。

假设我有一些对象A,它在构造时将自己添加为来自对象B 的事件的事件侦听器。由于对象具有将自身添加为侦听器所需的所有数据,因此它也具有将自身从侦听器中删除的数据。

很遗憾,GC 无法启动删除过程,因为对象将在侦听器列表中引用,直到明确删除。

因此,这意味着任何一个对象都不应该将自己添加为侦听器,或者应该有一种方法可以将某些引用标记为不重要。在后一种情况下,GC 会启动垃圾回收,即使存在对该对象的一些引用——如果它们只是“不重要”的情况。

显然,程序员应该有义务通过dispose或finalize等方法清除所有不重要的引用。

我知道这种直接实施将是一种安全漂白。例如,如果程序员违反了处置契约,垃圾回收会提供不正确的引用。

那么,问题是:是否有一些库或模式来实现这种关系?

【问题讨论】:

  • 对于侦听器的特定情况,您应该在不再需要它们时将其删除。其他情况可能会使用弱引用或 finalize(),但对于通常不起作用的侦听器。

标签: java garbage-collection disposable


【解决方案1】:

如果您只想将对象生命周期管理为对它的引用而不是作为侦听器,那么您可以将侦听器集合更改为像WeakHashMap 这样的“弱”集合。这样的集合使用Weak References 来避免在清除所有其他引用后使对象保持活动状态。

【讨论】:

    【解决方案2】:

    一般来说,当您希望某个对象被垃圾回收时,您应该将删除引用作为您的工作。这是在垃圾回收环境中管理内存的一部分。

    只是,例如:

    class MyInternalFrame extends JInternalFrame implements ActionListener {
        ...
    
        void removeSelfAndDispose() {
            for(JMenuItem button : parent.getMenuItems())
                button.removeActionListener(this);
            dispose();
        }
    }
    

    不过,最好避免存储这些持久性引用。例如,使用static 嵌套类而不是在容器上实现监听器。

    可以使用WeakReference 来构造一个不防止垃圾回收的侦听器,例如:

    class MyInternalFrame extends JInternalFrame {
        ...
    
        MyInternalFrame() {
            for(JMenuItem button : parent.getMenuItems())
                button.addActionListener(new WeakListener(this, button));
        }
    
        static class WeakListener implements ActionListener {
            final Reference<JInternalFrame> ref;
            final AbstractButton button;
    
            WeakListener(JInternalFrame frame, AbstractButton button) {
                ref = new WeakReference<JInternalFrame>(frame);
                this.button = button;
            }
    
            @Override
            public void actionPerformed(ActionEvent ae) {
                JInternalFrame frame = ref.get();
                if(frame == null) {
                    button.removeActionListener(this);
                    return;
                }
    
                ...
            }
        }
    }
    

    但这是粗略的,不应依赖。我们无法控制垃圾收集何时运行,因此这样做可能会导致不可预知的行为。 (我们保留引用的对象仍然存在,并在您认为它已被删除后响应事件。)

    简单地防止不需要的引用被放置或在适当的时候故意删除它们更可靠。

    【讨论】:

      【解决方案3】:

      查看 Java 中 Reference 的不同子类。我想这就是你要找的东西

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-22
        • 1970-01-01
        相关资源
        最近更新 更多