JDK-8048207 : CheckedQueue.offer calls wrong method on wrapped queue
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-06-21
  • Updated: 2015-10-13
  • Resolved: 2014-06-27
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.
8u25Fixed 9 b22Fixed

In java.util.Collections.CheckedQueue, the offer() method calls the add() method of the wrapped queue instead of offer(). They do not do the same thing!

This is the offending code:

    public boolean offer(E e) {
        return add(e);

Should be:

    public boolean offer(E e) {
        return queue.offer(e);

This bug can be reproduced always.

The same problem existed in 8 so replacing 8u5 with 8 in affectedVersion.

On what releases or builds do these tests fail, and do they pass on any releases or builds?

Failed JCK tests: api/java_util/Collections/checked/queue/index.html#Delegation[offerExceptionDelegation] api/java_util/Collections/checked/queue/index.html#Delegation[offer]

This issue isn't applicable for jdk7. So, PSU14_04-critical-request is not correct label for the bug fix as far as PSU14_04 is jdk7u72 only. In advance: SQE OK to take the bug fix into CPU14_04.

Some additional comments about risks and testing. It is possible applications have been written to use the current semantics though because of the behaviour difference between CheckedQueue and other Queue implementations the applications are likely to accept both the current CheckedQueue behaviour as well as the standard behaviour provided by other (correct) implementations. Since Collections.checkedQueue is a new feature in Java 8 it is unlikely that many applications yet depend upon the feature. In response to this bug the jtreg test suite was improved to test for both the erroneous condition as well as other similar conditions. The tests on Queue and Collections.checkedQueue() I would consider, at this point, generally inadequate though they now test this particular failure sufficiently.

It is important to backport this issue into the earliest possible JDK 8u release. The error is likely to be encountered by virtually all users of CheckedQueue and there no practical workarounds. The problem is encountered when using a bounded queue with Collections.checkedQueue(). If the wrapped queue is full then an IllegalStateException will be thrown rather than the expected result of offer() returning a false result. The IllegalStateException is not declared for Queue.offer() and it is unlikely that applications will handle this exception since other implementations of Queue.offer() do not throw this exception. Applications could be adapted to catch the exception but this is not practical. The mode of use which offers elements to the queue until offer() returns false is very common and this bug is a significant deviation from the method specification. The goal of Collections.checkedQueue is to provide a direct replacement for the standard queue with additional safety. This error substantially impairs Collections.checkedQueue() as a direct replacement for other Queue types.

The fix has been working it's way through the process and has been in jdk9 since June 27th and 8u-dev since July 7th.

This is P2 issue (for some reason the priority on the backport issue wasn't set). It needs to be fixed in 8uX.

Please defer since this is a P4 or come back with a better justification and SQE-OK.

This change should be backported to 8u20. The buggy implementation will result in an unexpected RuntimeException that applications are unlikely to handle correctly. The error also prevents CheckedQueue from being a usable direct replacement for the queue it wraps as the differing behaviours are conflicting.

q.add() can throw an exception, while q.offer() would only return false.