JDK-8202260 : (ref) Reference objects should not support cloning
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11
  • Submitted: 2018-04-25
  • Updated: 2022-04-20
  • Resolved: 2018-05-01
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Update `Reference::clone` to always throw `CloneNotSupportedException`.

Problem
-------

The semantics of cloning a reference object (any instance of `java.lang.ref.Reference`) are not clearly defined.
In addition, it is questionable whether cloning should be supported due
to its tight interaction with garbage collector.

The reachability state of a reference object may change during
GC reference processing.  The reference object may have been cleared
when it reaches its reachability state.  On the other hand, it may
be enqueued or pending for enqueuing.   A newly cloned reference
object could have a referent that is unreachable if the reference
object being cloned is not yet cleared.  A newly cloned reference
object from an enqueued reference object will never be enqueued.

A reference object cannot be meaningfully cloned.

Solution
--------

Update `Reference::clone` to always throw `CloneNotSupportedException`.
To clone a reference object, user code should create a new reference object with a constructor.

Specification
-------------

```
+    /**
+     * Throws {@link CloneNotSupportedException}. A {@code Reference} cannot be
+     * meaningfully cloned. Construct a new {@code Reference} instead.
+     *
+     * @returns never returns normally
+     * @throws  CloneNotSupportedException always
+     *
+     * @since 11
+     */
+    @Override
+    protected Object clone() throws CloneNotSupportedException {
+        throw new CloneNotSupportedException();
+    }
+
```



Comments
[~darcy] I will add the release note ("release-note=yes" label added). Regarding the question about any other methods inherited from Object should be intercepted, I think no other method needs to be intercepted (see below). Each Reference object is distinct and there isn't a strong reason to change equals/hashCode to justify the incompatibility. Multiple clients can create a Reference of the same referent. The garbage collector will clear and enqueue the Reference objects for notification. Adding a final "finalize" method has the incompatibility risk and I don't see a compelling case to do so. The referent is cleared when it reaches its reachability state. There is no way to resurrect the referent from Reference::finalize method since Reference::get returns null if cleared. It may be useful to have a user-friendly toString output. Accessing the referent may interfere concurrent GC implementation. It would be best to add that when JDK-8188055 is implemented. I added a comment in JDK-8188055.
03-05-2018

Moving to Approved with a few comments: Please add a release note for this change given the small but real potential for compatibility impact on custom sub-sub-classes of Reference (as Reference is not directly subclassable outside of the JDK but its child classes are). Should any other of the methods inherited from Object be intercepted by java.lang.ref.Reference? A final "finalize" method that calls super.finalize()? A friendly toString() output?
01-05-2018

Updated per recommendation and finalized.
27-04-2018

Recommend: @return never returns normally
26-04-2018