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.
Threads are top level objects. They are 'special' so they do not follow the same rules as other objects. The do not rely on references to keep them 'alive' (i.e. safe from GC). A thread will not get garbage collected until it has ended. Which doesn't happen in your sample code, since the thread is blocked. Of course, now that the thread object is not garbage collected, then any other object referenced by it (the queue in your case) also cannot be garbage collected.
You are creating threads indefinitely because they all block until ArrayBlockingQueue<Integer> abq
has some entry. So eventually you'll get a OutOfMemoryError
.
(edit)
Each thread you create will never end because it blocks until the abq
queue as one entry.
If the thread is running, the GC isn't going to collect any object that the thread is referencing including the queue abq
and the thread itself.
abq.put(0);
should save your day.
Your threads all wait on their queue's take()
but you never put anything in those queues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With