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

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

但我发现我的程序会随着时间的推移泄漏内存。我做错了什么?

有帮助吗?

解决方案

这是Java 1.4中的已知错误: http://bugs.sun.com/bugdatabase/view_bug 。做; 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会很快耗尽内存。但是,运行测试代码表明,无论目前构建的MyThread数量是多少,JVM都使用少量的内存。我声称这是因为MyThread的实例被垃圾收集。

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top