简体   繁体   English

这会导致内存泄漏吗?

[英]Does this causes memory leak?

I have recently read some SO posts/answers that suggest using anonymous class could cause memory leak. 我最近阅读了一些SO帖子/答案,建议使用匿名类可能导致内存泄漏。 If I understood correctly, if an anonymous class' object reference leaks outside of the enclosing class, that could cause that anonymous class instance to be garbage non-collectible. 如果我理解正确,如果匿名类的对象引用泄漏到封闭类之外,则可能导致该匿名类实例无法收集垃圾。

Just to make sure I understood correctly, am I right to say the below sample code would not cause memory leak? 只是为了确保我理解正确,我是否正确地说下面的示例代码不会导致内存泄漏?

public class EnclosingClass {
    private AnonymousClassBase anonymous;

    public void startDoingSomething() {
        this.anonymous = new AnonymousClassBase() {
            @Override public void anonymouslyDoSomething() {
                EnclosingClass.this.doSomething("Did something anonymously!");
            }
        };
        this.anonymous.anonymouslyDoSomething();
    }

    private void doSomething(final String something) {
        System.out.println(something);
    }
}

public abstract class AnonymousClassBase {
    public abstract void anonymouslyDoSomething();
}

public class MainClass {
    private final EnclosingClass enclosing = new EnclosingClass();

    // Some kind of button click event handler
    public void onButtonClicked() {
        this.enclosing.startDoingSomething();
    }
}

The private field anonymous can only store one instance of AnonymousClassBase , so calling startDoingSomething() the second time will cause the enclosing class to lose the reference of the first instance. 私有字段anonymous只能存储一个AnonymousClassBase实例,因此第二次调用startDoingSomething()将导致封闭类丢失第一个实例的引用。 At this point, is that first instance eligible for garbage collection? 在这一点上,第一个实例是否有资格进行垃圾收集?

Just to give an update what I found so others can hopefully benefit from it. 只是为了更新我发现的内容,以便其他人可以从中受益。 I have further modified the codes to further illustrate the point: 我进一步修改了代码以进一步说明这一点:

public class EnclosingClass {
    private AnonymousClassBase anonymous;
    private Object enclosingClassField = new Object();

    public void startDoingSomething() {
        this.anonymous = new AnonymousClassBase() {
            // Takes some significant load on memory for each anonymous object
            private double[] memoryLoad = new double[9999999];

            // Just taking reference of something belonging to enclosing class
            private Object test = EnclosingClass.this.enclosingClassField;

            @Override public void anonymouslyDoSomething() {
                EnclosingClass.this.doSomething("Did something anonymously!");
            }
        };

        this.anonymous.anonymouslyDoSomething();
    }

    private void doSomething(final String something) {
        System.out.println(something);
    }
}

public abstract class AnonymousClassBase {
    public abstract void anonymouslyDoSomething();
}

public class MainClass {
    private final EnclosingClass enclosing = new EnclosingClass();

    // Some kind of button click event handler
    public void onButtonClicked() {
        this.enclosing.startDoingSomething();
    }
}

The main difference is that the anonymous object will each take a memory load of almost 76.3MB for each anonymous object. 主要区别在于匿名对象每个匿名对象的内存负载几乎为76.3MB。 The JVM slowly increased to approximately 2.9GB and dropped to about 300MB - which indicated that a garbage collection did occur to remove those anonymous class objects. JVM慢慢增加到大约2.9GB并下降到大约300MB - 这表明确实发生了垃圾收集以删除那些匿名类对象。

Therefore my conclusion is that anonymous class objects can hold reference of anything belonging to their enclosing class object. 因此,我的结论是匿名类对象可以保存属于其封闭类对象的任何内容的引用。 When the anonymous class object is holding a reference of something that even its enclosing class object no longer hold, then it will also lose reference of that. 当匿名类对象持有某个甚至其封闭类对象不再持有的东西的引用时,它也将失去对它的引用。 In certain sense, the anonymous class object is holding a weak reference of its enclosing class object, and any object reference belonging to the enclosing class object is derived from enclosing class (eg that enclosingClassField object in the example). 在某种意义上,匿名类对象持有其封闭类对象的弱引用 ,属于封闭类对象的任何对象引用都是从封闭类派生的(例如,在示例中enclosingClassField对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM