当我调用Thread对象的run()时,为什么我的Java程序会泄漏内存?

(危险的问题,我希望在我遇到这个问题时,答案已经在线)

使用Java 1.4,我有一种方法,我想在某些时候作为线程运行,而不是在其他时间运行。 所以我将它声明为Thread的子类,然后根据我需要的调用start()或run()。

但是我发现我的程序会随着时间流逝而泄漏内存。 我究竟做错了什么?


这是Java 1.4中的一个已知错误:http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=5869e03fee226ffffffffc40d4fa881a86e3:WuuT?bug_id=4533087

它在Java 1.5中修复,但Sun并不打算在1.4中修复它。

问题在于,在构建时, Thread被添加到内部线程表中的引用列表。 在start()方法完成之前,它不会从该列表中删除。 只要这个参考在那里,它就不会被垃圾收集。

所以,除非你一定要调用start()方法,否则不要创建线程。 Thread对象的run()方法不应该直接调用。

编写代码的更好方法是实现Runnable接口而不是子类Thread 。 当你不需要线程时,请致电

myRunnable.run();

当你确实需要一个线程时:

Thread myThread = new Thread(myRunnable);
myThread.start();

我怀疑构造一个Thread或其子类的实例会泄漏内存。 首先,在Javadocs或Java语言规范中没有提及的种类。 其次,我运行了一个简单的测试,并且还显示没有内存泄漏(至少不是在32位x86 Linux 2.6上的Sun JDK 1.5.0_05上):

public final class Test {
  public static final void main(String[] params) throws Exception {
    final Runtime rt = Runtime.getRuntime();
    long i = 0;
    while(true) {
      new MyThread().run();
      i++;
      if ((i % 100) == 0) {
        System.out.println((i / 100) + ": " + (rt.freeMemory() / 1024 / 1024) + " " + (rt.totalMemory() / 1024 / 1024));
      }
    }
  }

  static class MyThread extends Thread {
    private final byte[] tmp = new byte[10 * 1024 * 1024];

    public void run() {
      System.out.print(".");
    }
  }
}

编辑:只是为了总结上面的测试的想法。 Thread的MyThread子类的每个实例都引用其自己的10 MB数组。 如果MyThread的实例没有被垃圾收集,那么JVM会很快耗尽内存。 但是,运行测试代码表明,不管迄今为止构建的MyThreads的数量是多少,JVM都使用少量的内存。 我声称这是因为MyThread的实例被垃圾收集。


让我们看看我们是否能够接近问题的核心:

如果你开始你的程序(让我们说)1000 x使用开始(),然后1000 x使用run()在一个线程,做两个松散的内存? 如果是这样,那么应该检查你的算法(即对于外部对象,比如在你的Runnable中使用的向量)。

如果没有像上面描述的那样的内存泄漏,那么您应该调查有关JVM的线程的启动参数和内存使用情况。

链接地址: http://www.djcxy.com/p/16377.html

上一篇: Why is my Java program leaking memory when I call run() on a Thread object?

下一篇: Java: Static vs inner class