Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
FULL PRODUCT VERSION : tested on java version "1.8.0_05" Java(TM) SE Runtime Environment (build 1.8.0_05-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode) and java version "1.6.0_37" Java(TM) SE Runtime Environment (build 1.6.0_37-b06) Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01, mixed mode) ADDITIONAL OS VERSION INFORMATION : independent of OS tested on ubuntu : Linux pc-cap90 3.11.0-24-generic #41-Ubuntu SMP Mon Jun 9 20:36:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux EXTRA RELEVANT SYSTEM CONFIGURATION : to reproduce easily, small heap is helping (-Xmx4m) A DESCRIPTION OF THE PROBLEM : This test case with repeated offer and remove operations on ConcurrentLinkedQueue lead to an OutOfMemory Error. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Run the following test : // Quick OutOfMemory with -Xmx4m public void testOutOfMemory(){ ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>(); String a="a"; String b="b"; queue.offer(a); for(int i=0;;i++){ if(i % 1024 == 0) { System.out.println("i = "+i); } queue.offer(b); queue.remove(b); } } EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - No OutOfMemoryError. ACTUAL - i = 307200 i = 308224 i = 309248 i = 310272 java.lang.OutOfMemoryError: Java heap space at java.util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:274) at TestConcurrentLinkedQueue16.testOutOfMemory REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- public void testOutOfMemory(){ ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>(); String a="a"; String b="b"; queue.offer(a); for(int i=0;;i++){ if(i % 1024 == 0) { System.out.println("i = "+i); } queue.offer(b); queue.remove(b); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : When called on the last element of a ConcurrentLinkedQueue with more than 1 element, the remove method nullify the item but the Node object is not unlinked from the list. After many add/remove the queue structure is : a -> null -> ... -> null -> b To be garbage collected the Node objects with null item must be unlinked from the list. They are unlinked only when the queue is iterated or when the head is polled. The advance() method of the Iterator contains code that skip and unlink nodes with null item : private E advance() { lastRet = nextNode; E x = nextItem; Node<E> pred, p; if (nextNode == null) { p = first(); pred = null; } else { pred = nextNode; p = succ(nextNode); } for (;;) { if (p == null) { nextNode = null; nextItem = null; return x; } E item = p.item; if (item != null) { nextNode = p; nextItem = item; return x; } else { // skip over nulls Node<E> next = succ(p); if (pred != null && next != null) pred.casNext(p, next); p = next; } } } A fix could be to unlink the Node objects with null items while iterating on the elements in the remove method.
|