【问题标题】:[Java]Interfaces and memory leaks[Java]接口和内存泄漏
【发布时间】:2015-10-02 12:43:50
【问题描述】:

我对接口和内存泄漏有疑问,考虑到下面的代码块,它会导致内存泄漏吗? 如果是这样,最好的解决方案或替代方案是什么?

public class MyClass {
    public interface MyClassListener{
         doStuff();
    }

    public doSomething(){}
}

public class OtherClass {

    private List<MyClass> list = new ArrayList<MyClass>();
    private boolean doingStuff = false;

    public void setListener(MyClassListener list) { //Sets the listener}

    public MyClass.MyClassListener listener = new MyClass.MyClassListener() {
        public void doStuff(){ doingStuff = true; }
    }

    public void addMyClass(MyClass obj) {
        obj.setListener(listener);
        list.add(obj);
    }

    public void doSomethingInMyClass(int index) {
        ....update some stuff....
        list.get(index).doSomething();
    }
}

我知道我可以将变量listener 声明为static,因此它不会保留对OtherClass 的引用并将该引用分配给WeakReference,但我是否会出现内存泄漏? 由于引用将包含对包含我的对象的列表的对象的引用。它就像一条链子。

更新

我更新了我的问题,您可以看到MyClass 有一个名为doSomething() 的方法,而OtherClass 有一个名为doSomethingInMyClass 的方法,它调用doSomething 方法但更新了一些参数。 我想要的是避免使用doSomethingInMyClass 并且无论如何都会收到更改通知。

【问题讨论】:

  • 这就是所谓的自引用对象岛。当来自岛外的最后一个引用消失时,Java 的垃圾收集能够删除那些。
  • 表示当列表为空时会移除OtherClass对象?
  • 是的。 Java 垃圾收集以 活动线程 局部变量以及所有已加载类的 静态 成员开始。那些是第一层的生物。然后 GC 递归地标记从这些活对象引用的所有对象。其余的(取消引用对象)在 GC 之后从堆中删除。
  • 请看我的更新,我不想知道它是如何被垃圾收集的。

标签: java memory-leaks interface


【解决方案1】:

这是你的情况的一个例子:

interface I { }

class A {
    List<I> list = new ArrayList<>();
    void add(I item) { list.add(item); }
}

class B {
    A other;
    void setA(A a) {
        final B self = this;
        a.add(new I() { B owner = self; });
        other = a;
    }
}

[...]

public static void main (String[] args)
{                   // 1
    A a = new A();  // 2
    B b = new B();  // 3
    b.setA(a);      // 4
}                   // 5

main 的范围开始处,(1) 中的引用集为空。 ab 在 (4) 中设置为相互引用。然后在 (5) 中的范围末尾删除对 ab 的引用。结果是一个自引用对象的孤岛。

您可以按如下方式可视化一组(非null)引用:

  1. {}
  2. {a, a.list}
  3. {a, a.list, b}
  4. {a, a.list, a.list[0], a.list[0].owner, b, b.other}
  5. {a.list, a.list[0], a.list[0].owner, b.other}

最后,您在a 中引用了一个列表,它包含对B 中的内部I 的一个或多个引用,其中包含对其所有者b 的引用,其中包含对a。当垃圾收集器将此列表中每个对象的引用计数相加时,如果这些计数等于实际引用计数(即该列表是完全自引用的),它可以将它们全部删除。

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    相关资源
    最近更新 更多