Java线程: New他就Start他 (遇见JDK1.4.2_04以前的一个bug)

我们的系统有OutOfMemory现象, Liu同学最近又发现了一个原因:Sun JDK 1.4.2_04版本(含以前)的bug,

我们系统另一个OOM的原因参见:Derby: Out Of Memory & Update

对与sun的这个bug我以前一无所知, 有必要记录下来, 学习一下.

 

Bug现象:

一个线程如果只是new, 而没有start(), 那么该线程不会被垃圾回收,

我们系统使用的一个jar包(日方提供的), 里面有一个api, 功能是去网络上通过snmp协议取一个mib值,

反编译过来发现他有这种"只是new一个线程,并没有start"的问题,

于是系统持续运行就导致了OutOfMemory

 

另:该bug在jdk5,6 上测试,已经修正.

(艾~这么久的bug我们也能遇到,关于使用底版本的原因我就不另作点评了, 否则又要郁闷了...此处省略1W字^^)

 

下面这两个链接

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4533087

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508232

 

上面这两个链接已经将bug描述得很清楚了, 但是我害怕以后我会找不到这两个链接,

因为现在一些bea的东西我就已经找不到地方了, 所以见bug原因和测试代码抽出如下:

 

Bug4533087的测试代码:

 

class ThreadLeak {

	static MyThread t;

	public static void main(String[] args) {

		if ((args.length > 0) && args[0].equals("run")) {
			System.out.println("Creating and running 10,000 threads...");
			for (int i = 0; i < 10000; i++) {
				t = new MyThread(true);
			}
		} else {
			System.out
					.println("Creating 10,000 threads, but not running them...");
			for (int i = 0; i < 10000; i++) {
				t = new MyThread(false);
			}
		}

		System.out.println("Running garbage collector...");
		System.gc();

		System.out.println("Done.  Heap size is "
				+ (Runtime.getRuntime().totalMemory() - Runtime.getRuntime()
						.freeMemory()));
	}
}

class MyThread implements Runnable {

	Thread t;

	public MyThread(boolean bRun) {
		t = new Thread(this, "MyThread");
		if (bRun) {
			t.start();
		}
	}

	public void run() {
		/* NO-OP */
	}
}
 

 

 

Bug4508232的测试代码:

 

package thread;

//   AliveTest.java:   program to test theory that Threads which are not started
//                     are not garbage collected

//   - We create "T" Threads but don't "start" them.  The output shows:
//      a)  that creation is fast (compared to -starting- Threads)
//      b)  that memory is garbage collected
//      c)  the Thread ACTIVE count always increases
//      d) eventually we run out of memory

public class AliveTest {

	public static void main(String[] args) {
		long t1 = System.currentTimeMillis();
		Runtime r = Runtime.getRuntime();

		for (int i = 1;; i++) {
			//OK
			new T().start();
			
			//OutOfMemory
			//new T();
			if (i % 100 == 0) {
				System.out.println("Threads created: " + i + ", t: "
						+ (System.currentTimeMillis() - t1) / 1000
						+ " sec, activeCount: " + Thread.activeCount()
						+ ",   Free mem:" + r.freeMemory() / 1000 + " K");
			}
		}
	}

}

class T extends Thread {
	int[] a = new int[10000];

	public void run() {
		a[0] = 1;
	}
}

 

Bug4533087中对原因的描述:

 

写道
The reason is that the java.lang.Thread class adds the thread to the thread group in the init() method, which is called from the constructor. It removes the thread from the thread group in the exit() method, which is only called if the thread is run. So if the thread is never run, the thread group still has a reference to the Thread and it will never be garbage collected. And of course any objects which the thread has references to will in turn not be garbage collected.
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值