Skip to content

Commit 637e9d1

Browse files
Vicente Romeroarchiecobbs
andcommitted
8354556: Expand value-based class warnings to java.lang.ref API
Co-authored-by: Archie Cobbs <acobbs@openjdk.org> Reviewed-by: jlahoda
1 parent fbeea1d commit 637e9d1

32 files changed

+610
-85
lines changed

make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,18 @@ public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFil
304304
"Ljdk/internal/ValueBased;";
305305
private static final String VALUE_BASED_ANNOTATION_INTERNAL =
306306
"Ljdk/internal/ValueBased+Annotation;";
307+
private static final String REQUIRES_IDENTITY_ANNOTATION =
308+
"Ljdk/internal/RequiresIdentity;";
309+
private static final String REQUIRES_IDENTITY_ANNOTATION_INTERNAL =
310+
"Ljdk/internal/RequiresIdentity+Annotation;";
307311
public static final Set<String> HARDCODED_ANNOTATIONS = new HashSet<>(
308312
List.of("Ljdk/Profile+Annotation;",
309313
"Lsun/Proprietary+Annotation;",
310314
PREVIEW_FEATURE_ANNOTATION_OLD,
311315
PREVIEW_FEATURE_ANNOTATION_NEW,
312316
VALUE_BASED_ANNOTATION,
313-
RESTRICTED_ANNOTATION));
317+
RESTRICTED_ANNOTATION,
318+
REQUIRES_IDENTITY_ANNOTATION));
314319

315320
private void stripNonExistentAnnotations(LoadDescriptions data) {
316321
Set<String> allClasses = data.classes.name2Class.keySet();
@@ -1021,6 +1026,12 @@ private Annotation createAnnotation(AnnotationDescription desc) {
10211026
annotationType = VALUE_BASED_ANNOTATION_INTERNAL;
10221027
}
10231028

1029+
if (REQUIRES_IDENTITY_ANNOTATION.equals(annotationType)) {
1030+
//the non-public RequiresIdentity annotation will not be available in ct.sym,
1031+
//replace with purely synthetic javac-internal annotation:
1032+
annotationType = REQUIRES_IDENTITY_ANNOTATION_INTERNAL;
1033+
}
1034+
10241035
if (RESTRICTED_ANNOTATION.equals(annotationType)) {
10251036
//the non-public Restricted annotation will not be available in ct.sym,
10261037
//replace with purely synthetic javac-internal annotation:
@@ -2202,6 +2213,7 @@ private boolean readAttribute(FeatureDescription feature, Attribute<?> attr) {
22022213
chd.permittedSubclasses = a.permittedSubclasses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList());
22032214
}
22042215
case ModuleMainClassAttribute a -> ((ModuleHeaderDescription) feature).moduleMainClass = a.mainClass().asInternalName();
2216+
case RuntimeVisibleTypeAnnotationsAttribute a -> {/* do nothing for now */}
22052217
default -> throw new IllegalArgumentException("Unhandled attribute: " + attr.attributeName()); // Do nothing
22062218
}
22072219

src/java.base/share/classes/java/lang/ref/Cleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public static Cleaner create(ThreadFactory threadFactory) {
219219
* @param action a {@code Runnable} to invoke when the object becomes phantom reachable
220220
* @return a {@code Cleanable} instance
221221
*/
222-
public Cleanable register(Object obj, Runnable action) {
222+
public Cleanable register(@jdk.internal.RequiresIdentity Object obj, Runnable action) {
223223
Objects.requireNonNull(obj, "obj");
224224
Objects.requireNonNull(action, "action");
225225
return new CleanerImpl.PhantomCleanableRef(obj, this, action);

src/java.base/share/classes/java/lang/ref/PhantomReference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
* @since 1.2
5252
*/
5353

54-
public non-sealed class PhantomReference<T> extends Reference<T> {
54+
public non-sealed class PhantomReference<@jdk.internal.RequiresIdentity T> extends Reference<T> {
5555

5656
/**
5757
* Returns this reference object's referent. Because the referent of a
@@ -101,7 +101,7 @@ void clearImpl() {
101101
* @param q the queue with which the reference is to be registered,
102102
* or {@code null} if registration is not required
103103
*/
104-
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
104+
public PhantomReference(@jdk.internal.RequiresIdentity T referent, ReferenceQueue<? super T> q) {
105105
super(referent, q);
106106
}
107107

src/java.base/share/classes/java/lang/ref/Reference.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* @sealedGraph
4545
*/
4646

47-
public abstract sealed class Reference<T>
47+
public abstract sealed class Reference<@jdk.internal.RequiresIdentity T>
4848
permits PhantomReference, SoftReference, WeakReference, FinalReference {
4949

5050
/* The state of a Reference object is characterized by two attributes. It

src/java.base/share/classes/java/lang/ref/ReferenceQueue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
* @since 1.2
4747
*/
4848

49-
public class ReferenceQueue<T> {
49+
public class ReferenceQueue<@jdk.internal.RequiresIdentity T> {
5050
private static class Null extends ReferenceQueue<Object> {
5151
@Override
5252
boolean enqueue(Reference<?> r) {

src/java.base/share/classes/java/lang/ref/SoftReference.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
* @since 1.2
6363
*/
6464

65-
public non-sealed class SoftReference<T> extends Reference<T> {
65+
public non-sealed class SoftReference<@jdk.internal.RequiresIdentity T> extends Reference<T> {
6666

6767
/**
6868
* Timestamp clock, updated by the garbage collector
@@ -82,7 +82,7 @@ public non-sealed class SoftReference<T> extends Reference<T> {
8282
*
8383
* @param referent object the new soft reference will refer to
8484
*/
85-
public SoftReference(T referent) {
85+
public SoftReference(@jdk.internal.RequiresIdentity T referent) {
8686
super(referent);
8787
this.timestamp = clock;
8888
}
@@ -96,7 +96,7 @@ public SoftReference(T referent) {
9696
* or {@code null} if registration is not required
9797
*
9898
*/
99-
public SoftReference(T referent, ReferenceQueue<? super T> q) {
99+
public SoftReference(@jdk.internal.RequiresIdentity T referent, ReferenceQueue<? super T> q) {
100100
super(referent, q);
101101
this.timestamp = clock;
102102
}

src/java.base/share/classes/java/lang/ref/WeakReference.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@
4646
* @since 1.2
4747
*/
4848

49-
public non-sealed class WeakReference<T> extends Reference<T> {
49+
public non-sealed class WeakReference<@jdk.internal.RequiresIdentity T> extends Reference<T> {
5050

5151
/**
5252
* Creates a new weak reference that refers to the given object. The new
5353
* reference is not registered with any queue.
5454
*
5555
* @param referent object the new weak reference will refer to
5656
*/
57-
public WeakReference(T referent) {
57+
public WeakReference(@jdk.internal.RequiresIdentity T referent) {
5858
super(referent);
5959
}
6060

@@ -66,7 +66,7 @@ public WeakReference(T referent) {
6666
* @param q the queue with which the reference is to be registered,
6767
* or {@code null} if registration is not required
6868
*/
69-
public WeakReference(T referent, ReferenceQueue<? super T> q) {
69+
public WeakReference(@jdk.internal.RequiresIdentity T referent, ReferenceQueue<? super T> q) {
7070
super(referent, q);
7171
}
7272

src/java.base/share/classes/java/util/WeakHashMap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132
* @see java.util.HashMap
133133
* @see java.lang.ref.WeakReference
134134
*/
135-
public class WeakHashMap<K,V>
135+
public class WeakHashMap<@jdk.internal.RequiresIdentity K,V>
136136
extends AbstractMap<K,V>
137137
implements Map<K,V> {
138138

@@ -457,7 +457,7 @@ Entry<K,V> getEntry(Object key) {
457457
* (A {@code null} return can also indicate that the map
458458
* previously associated {@code null} with {@code key}.)
459459
*/
460-
public V put(K key, V value) {
460+
public V put(@jdk.internal.RequiresIdentity K key, V value) {
461461
Object k = maskNull(key);
462462
int h = hash(k);
463463
Entry<K,V>[] tab = getTable();
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package jdk.internal;
27+
28+
import java.lang.annotation.Retention;
29+
import java.lang.annotation.RetentionPolicy;
30+
import java.lang.annotation.Target;
31+
32+
import static java.lang.annotation.ElementType.PARAMETER;
33+
import static java.lang.annotation.ElementType.TYPE_PARAMETER;
34+
35+
/**
36+
* Indicates that the annotated parameter or type parameter is not expected to be a
37+
* Value Based class.
38+
* Using a parameter or type parameter of a <a href="../lang/doc-files/ValueBased.html">value-based classes</a>
39+
* should produce warnings about behavior that is inconsistent with identity based semantics.
40+
*
41+
* Note this internal annotation is handled specially by the javac compiler.
42+
* To work properly with {@code --release older-release}, it requires special
43+
* handling in {@code make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java}
44+
* and {@code src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java}.
45+
*
46+
* @since 25
47+
*/
48+
@Retention(RetentionPolicy.RUNTIME)
49+
@Target(value={PARAMETER, TYPE_PARAMETER})
50+
public @interface RequiresIdentity {
51+
}

src/java.base/share/classes/jdk/internal/ValueBased.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,3 @@
4646
@Target(value={TYPE})
4747
public @interface ValueBased {
4848
}
49-

0 commit comments

Comments
 (0)