我刚刚接受了一次采访,被要求用Java创建内存泄漏。

不用说,我觉得自己很傻,不知道如何开始创作。

什么样的例子?


当前回答

一种可能是为ArrayList创建一个包装器,该包装器只提供一个方法:一个向ArrayList添加内容的方法。将ArrayList本身设为私有。现在,在全局范围中构造这些包装器对象之一(作为类中的静态对象),并用final关键字限定它(例如,public static final ArrayListWrapper wrapperClass=new ArrayListWrapper())。因此,现在不能更改引用。也就是说,wrapperClass=null不起作用,不能用于释放内存。但是除了向wrapperClass中添加对象之外,也没有办法对wrapperClass进行任何操作。因此,添加到wrapperClass中的任何对象都不可能被回收。

其他回答

要做的一件简单的事情是使用带有不正确(或不存在)hashCode()或equals()的HashSet,然后继续添加“重复项”。而不是像应该的那样忽略重复项,集合只会增长,您将无法删除它们。

如果你想让这些坏键/元素到处乱动,你可以使用一个静态字段,比如

class BadKey {
   // no hashCode or equals();
   public final String key;
   public BadKey(String key) { this.key = key; }
}

Map map = System.getProperties();
map.put(new BadKey("key"), "value"); // Memory leak even if your threads die.

在具有自己生命周期的类中随意使用非静态内部类。

在Java中,非静态内部类和匿名类对其外部类具有隐式引用。另一方面,静态内部类则不然。

下面是一个常见的Android内存泄漏示例,但这并不明显:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() { // Non-static inner class, holds the reference to the SampleActivity outer class
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for a long time.
    mLeakyHandler.postDelayed(new Runnable() {//here, the anonymous inner class holds the reference to the SampleActivity class too
      @Override
      public void run() {
     //....
      }
    }, SOME_TOME_TIME);

    // Go back to the previous Activity.
    finish();
  }}

这将防止活动上下文被垃圾收集。

GUI代码中的一个常见示例是创建小部件/组件并向某个静态/应用程序范围的对象添加侦听器,然后在小部件被破坏时不删除侦听器。不仅会出现内存泄漏,而且性能也会受到影响,因为无论你听什么都会引发事件,所有的老听众都会被调用。

一些建议:

在servlet容器中使用commons日志记录(可能有点挑衅)在servlet容器中启动线程,不要从其运行方法返回在servlet容器中加载动画GIF图像(这将启动一个动画线程)

通过重新部署应用程序,可以“改善”上述效果;)

我最近偶然发现:

调用“newjava.util.zip。充气器();”而不调用“充气器.end()”

阅读http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5072161并将问题联系起来进行深入讨论。

如果不使用压缩垃圾收集器,则可能会由于堆碎片而发生某种内存泄漏。