JDK-6457125 : ArrayBlockingQueue.poll(long, TimeUnit) memory leak
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2006-08-04
  • Updated: 2011-02-16
  • Resolved: 2006-08-04
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03)
Java HotSpot(TM) Client VM (build 1.5.0_07-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux neonato 2.6.16-gentoo-r12 #1 Sat Jul 8 18:15:37 CEST 2006 i686 Intel(R) Pentium(R) M processor 1400MHz GenuineIntel GNU/Linux

EXTRA RELEVANT SYSTEM CONFIGURATION :
Problem occurs even on a Fedora Core 4 system (don't have the full os version string at the moment)

A DESCRIPTION OF THE PROBLEM :
java.util.concurrent.ArrayBlockingQueue.poll(long, TimeUnit) suffers of a memory leak.
Using a profiler, I was able to see a huge number of
java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
instances created and never being collected by the GC.
The amount of memory occupied depends on how often the queue is queried for new objects.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Without a profiler: the fast way
Compile the attached example.
Run the example with
java Test 1

With a profiler
Run the example with a less aggressive argument such as 10 and attach a profiler to it.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In both cases, the program should run indefinetely with a very small memory footprint
ACTUAL -
In the first case
Your system will slow down a bit, with the processor at 100%. After something like 40seconds (on my system) you'll see an OutOfMemoryError

In the second case
See the number of Node objects increasing without ever being garbage collected

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

public class Test implements Runnable {

	public ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
	public long timeout;

	public Test(long timeout) {
		this.timeout = timeout;
	}
	

	public void run() {
		while (true) {
			try {
				queue.poll(timeout, TimeUnit.MICROSECONDS);
			} catch (InterruptedException e) {
				//nothing
			}
		}
	}
	
	public static void main(String[] args) {
		Test t = new Test(Long.parseLong(args[0]));
		new Thread(t).start();
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The problem has been temporarily solved by using a different syntax

queue.poll();
Thread.sleep(10);

That said, the poll() method doesn't seem to suffer the above problem.

Comments
EVALUATION This is a dup of 6236036: Timeouts can cause garbage retention in lock classes Here's the canonical minimal test case: ------------- import java.util.concurrent.*; public class Bug { public static void main(String[] args) throws Throwable { BlockingQueue<String> q = new ArrayBlockingQueue<String>(10); while (true) q.poll(10, TimeUnit.NANOSECONDS); } } -------------
04-08-2006