2017-06-12 125 views
1

我最近读了一些SO帖子/答案,建议使用匿名类可能会导致内存泄漏。如果我理解正确,如果匿名类的对象引用泄漏到封闭类之外,那可能会导致匿名类实例变得无法收集。这是否会导致内存泄漏?

为了确保我的理解正确,我是否正确地说下面的示例代码不会导致内存泄漏?

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(); 
    } 
} 

私人领域anonymous只能存储AnonymousClassBase一个实例,因此调用startDoingSomething()第二次将导致封闭类失去一审参考。此时,是否有资格进行垃圾回收?

+0

当你用匿名共享你的类变量时发生内存泄漏(并且在使用后不要将它们取消设置) – FieryCat

+0

嗯,我在匿名类中添加了'private double [] memoryLoad = new double [9999999];'看起来像我的机器上的JVM在内存消耗达到2.9GB之后做垃圾回收。所以看起来好像我回答了我自己的问题...... – Jai

+0

好的问题已经是答案的一半:) – FieryCat

回答

0

只是为了给我更新我发现的东西,以便其他人可以从中受益。我已进一步修饰的代码来进一步说明这一点:

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(); 
    } 
} 

的主要区别是匿名对象将各采取几乎76.3MB的存储器加载用于每个​​匿名对象。 JVM缓慢增加到大约2.9GB并下降到大约300MB - 这表明垃圾收集确实发生,以去除这些匿名类对象。

因此,我的结论是,匿名类对象可以容纳任何属于它们的封闭类对象的引用。当匿名类对象持有一个引用,即使它的封闭类对象不再存在时,它也将失去引用。在某种意义上,匿名类对象持有其封闭类对象的弱引用,并且属于封闭类对象的任何对象引用都是从封闭类(例如该示例中的enclosingClassField对象)派生而来的。

相关问题