当我调用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?