JDK-6215625 : LinkedBlockingQueue.extract throws NPE
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-01-10
  • Updated: 2010-04-02
  • Resolved: 2005-09-04
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.
Other JDK 6
5.0u6Fixed 6 b51Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
windows XP sp1

A DESCRIPTION OF THE PROBLEM :
public class TaskPool {
    public static void main( String[] args ) throws InterruptedException {
        LinkedBlockingQueue lbq = new LinkedBlockingQueue();
        Integer one = 1;
        Integer two = 2;
        Integer three = 3;
        lbq.put(one);
        lbq.put(two);
        lbq.remove(one);
        lbq.remove(two);
        lbq.put(three);
        System.out.println(lbq.take());
    }
}

java  TaskPool

Exception in thread "main" java.lang.NullPointerException

    at java.util.concurrent.LinkedBlockingQueue.extract(Unknown Source)
    at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
    at TaskPool.main(TaskPool.java:23)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
java  TaskPool

ACTUAL -
Exception in thread "main" java.lang.NullPointerException

    at java.util.concurrent.LinkedBlockingQueue.extract(Unknown Source)
    at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
    at TaskPool.main(TaskPool.java:23)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException

    at java.util.concurrent.LinkedBlockingQueue.extract(Unknown Source)
    at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
    at TaskPool.main(TaskPool.java:23)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.concurrent.LinkedBlockingQueue;

public class TaskPool {
    public static void main( String[] args ) throws InterruptedException {
        LinkedBlockingQueue lbq = new LinkedBlockingQueue();
        Integer one = 1;
        Integer two = 2;
        Integer three = 3;
        lbq.put(one);
        lbq.put(two);
        lbq.remove(one);
        lbq.remove(two);
        lbq.put(three);
        System.out.println(lbq.take());
    }
}
---------- END SOURCE ----------
###@###.### 2005-1-10 12:08:56 GMT

Comments
SUGGESTED FIX --- /u/martin/ws/mustang/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java 2005-08-07 16:20:18.348629000 -0700 +++ /u/martin/ws/lbq/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java 2005-08-19 09:30:38.939209000 -0700 @@ -469,6 +469,8 @@ if (removed) { p.item = null; trail.next = p.next; + if (last == p) + last = trail; if (count.getAndDecrement() == capacity) notFull.signalAll(); } @@ -675,6 +677,8 @@ if (p == node) { p.item = null; trail.next = p.next; + if (last == p) + last = trail; int c = count.getAndDecrement(); if (c == capacity) notFull.signalAll(); --- /u/martin/ws/mustang/test/java/util/concurrent/LinkedBlockingQueue/LastElement.java 1969-12-31 16:00:00.000000000 -0800 +++ /u/martin/ws/lbq/test/java/util/concurrent/LinkedBlockingQueue/LastElement.java 2005-08-19 10:12:06.147278000 -0700 @@ -0,0 +1,82 @@ +/* + * @test %I% %E% + * @bug 6215625 + * @summary Check correct behavior when last element is removed. + * @author Martin Buchholz + */ + +import java.util.*; +import java.util.concurrent.*; + +public class LastElement { + static int passed = 0, failed = 0; + + static void fail(String msg) { + failed++; + new Exception(msg).printStackTrace(); + } + + static void pass() { + passed++; + } + + static void unexpected(Throwable t) { + failed++; + t.printStackTrace(); + } + + static void check(boolean condition, String msg) { + if (condition) + passed++; + else + fail(msg); + } + + static void check(boolean condition) { + check(condition, "Assertion failure"); + } + + public static void main(String[] args) throws Throwable { + testQueue(new LinkedBlockingQueue<Integer>()); + // Uncomment when LinkedBlockingDeque is integrated + //testQueue(new LinkedBlockingDeque<Integer>()); + testQueue(new ArrayBlockingQueue<Integer>(10)); + + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new Exception("Some tests failed"); + } + + private static void testQueue(BlockingQueue<Integer> q) throws Throwable { + Integer one = 1; + Integer two = 2; + Integer three = 3; + + // remove(Object) + q.put(one); + q.put(two); + check(! q.isEmpty() && q.size() == 2); + check(q.remove(one)); + check(q.remove(two)); + check(q.isEmpty() && q.size() == 0); + q.put(three); + try {check(q.take() == three);} + catch (Throwable t) {unexpected(t);} + check(q.isEmpty() && q.size() == 0); + + // iterator().remove() + q.clear(); + q.put(one); + check(q.offer(two)); + check(! q.isEmpty() && q.size() == 2); + Iterator<Integer> i = q.iterator(); + check(i.next() == one); + i.remove(); + check(i.next() == two); + i.remove(); + check(q.isEmpty() && q.size() == 0); + q.put(three); + try {check(q.take() == three);} + catch (Throwable t) {unexpected(t);} + check(q.isEmpty() && q.size() == 0); + } +}
19-08-2005

EVALUATION Doug Lea writes: "This is the same problem as in bug 6189072 but in a different place. Worse, the same problem was also in iterator.remove(); Very sorry for not checking for these when fixing 6189072. Fixes are checked into our CVS. " ###@###.### 2005-1-11 23:30:51 GMT
11-01-2005