This simple sample code demonstrates the problem. I create an ArrayBlockingQueue
, and a thread that waits for data on this queue using take()
. After the loop is over, in theory both the queue and the thread can be garbage collected, but in practice I soon get an OutOfMemoryError
. What is preventing this to be GC'd, and how can this be fixed?
/**
* Produces out of memory exception because the thread cannot be garbage
* collected.
*/
@Test
public void checkLeak() {
int count = 0;
while (true) {
// just a simple demo, not useful code.
final ArrayBlockingQueue<Integer> abq = new ArrayBlockingQueue<Integer>(2);
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
abq.take();
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
// perform a GC once in a while
if (++count % 1000 == 0) {
System.out.println("gc");
// this should remove all the previously created queues and threads
// but it does not
System.gc();
}
}
}
I am using Java 1.6.0.
UPDATE: perform GC after a few iterations, but this does not help.