JDK-6815766 : LinkedBlockingQueue's iterator can return null if drainTo(c) executes concurrently
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2009-03-11
  • Updated: 2010-04-04
  • Resolved: 2009-08-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
7 b70Fixed
Related Reports
Relates :  
Martin Buchholz reports:

The following test program should never throw,
but it quickly throws NullPointerException.

import java.util.*;
import java.util.concurrent.*;

public class LBQRace {
    static void checkNotContainsNull(Iterable it) {
        for (Object x : it)
            if (x == null)
                throw new NullPointerException();

    public static void main(String[] args) throws Throwable {
        final BlockingQueue q = new LinkedBlockingQueue();

        new Thread() { public void run() {
            for (;;) {

        new Thread() { public void run() {
            for (;;) {
                List list = new ArrayList();

        new Thread() { public void run() {
            for (;;) {

EVALUATION changeset containing this fix: http://hg.openjdk.java.net/jdk7/tl/jdk/rev/49573ab3096a

SUGGESTED FIX Simple solution: move the element copy inside the locked section - as occurs with the drainTo(Collection c, int maxElements) method. More complex: in the loop that does the copy unlink each Node as the chain is traversed. This will prevent the iterator from continuing down the deleted chain. In Itr.next() check for a null item and treat it as finding a null next element.

EVALUATION The drainTo(Collection c) methods unlinks the current chain of elements while under protection of the queue's locks but then copies across each item to the target collection without a lock: // Transfer the elements outside of locks int n = 0; for (Node<E> p = first; p != null; p = p.next) { c.add(p.item); p.item = null; ++n; } If an iterator() already has one of the Nodes as its current element then upon advancing to the next element it could encounter a null item which is subsequently returned from next(). As null is not a permitted element in the queue it should never be returned.