Omission in javadoc Stream.toArray(): Safe array contract stipulation

Reinier Zwitserloot reinier at zwitserloot.com
Thu Dec 14 13:46:59 UTC 2023


Hi core libs team,

I think I found a rather inconsequential and esoteric bug, though the term
is somewhat less objectively defined when the problem exists solely in how
complete some method’s javadoc is.

Two questions: Is there a plausible argument that the javadoc as is,
shouldn’t be updated? If not, what’s the right place to report this javadoc
‘bug’?

The issue:

A snippet of the javadoc of Collection.toArray, from current HEAD jdk22u:

    <p>The returned array will be "safe" in that no references to it are
     * maintained by this collection.  (In other words, this method must
     * allocate a new array even if this collection is backed by an array).
     * The caller is thus free to modify the returned array.

The javadoc of Stream.toArray, from current HEAD jdk22u - has no such rider
anywhere in its documentation nor on the javadoc of the Stream interface,
nor on the package javadoc. The javadoc is quite short; the complete docs
on toArray():

     /**
     * Returns an array containing the elements of this stream.
     *
     * <p>This is a <a href="package-summary.html#StreamOps">terminal
     * operation</a>.
     *
     * @return an array, whose {@linkplain Class#getComponentType runtime
component
     * type} is {@code Object}, containing the elements of this stream
     */

The more usually used variant taking a function that makes the array has
slightly longer javadoc, but it similarly makes no mention whatsoever about
the contract stipulation that any implementors must not keep a reference.

A snippet from Stuart Marks on a stack overflow question about a to the
asker weird choice about stream’s toList()’s default implementation (
https://stackoverflow.com/questions/77473755/is-it-necessary-to-copy-a-list-to-be-safe/77474199?noredirect=1#comment136909551_77474199
):

    @Holger The extra step in the default implementation is there to force
a defensive copy if this.toArray were to violate its spec and keep a
reference to the returned array. Without the defensive copy, it would be
possible to modify the list returned from the default toList implementation.



Which leads to the obvious question: Where is that ’spec’ that Stuart is
referring to? Either the javadoc is the spec and therefore the javadoc is
buggy, in that it fails to mention this stipulation, or the spec is
elsewhere, in which case surely the javadoc should link to it or copy it.

Possibly this is jus filed away as: “Unlike with Collection, Stream
instances are disposable; after a terminal operation (and toArray is
terminal) has been invoked on it, that stream object has ceased being
useful. Therefore, there is no perceived value to caching any created
array, therefore, it doesn’t need mentioning".

Except, as per Stuart’s comment, actual OpenJDK code is written partly to
deal with any violators of this invisible spec, and the discrepancy (where
Collection.toArray explicitly mentions the contract stipulation that
toArray() must make safe arrays, but Stream’s toArray() does not) suggests
a fundamental difference where none exists (in fact, literally: Apparently
its a spec violation if your Stream implementation return a non-safe array
from toArray!)

 --Reinier Zwitserloot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20231214/eaebaadd/attachment-0001.htm>


More information about the core-libs-dev mailing list