diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 5d64683f637..7ed4d0cbcce 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -631,6 +631,13 @@ public static Class forName(Module module, String name) { * {@code Class} object represents an interface, array type, primitive type, * or {@code void}, the result is {@code false}. * + *

This method returns {@code true} if and only if this {@code Class} + * object represents a class that uses preview features, and the class does + * not have the {@link AccessFlag#IDENTITY ACC_IDENTITY} flag set. + * The {@code ACC_IDENTITY} flag is considered always set for a class that + * does not use preview features; consequently, this method always returns + * {@code false} when preview features are disabled. + * * @jls value-objects-8.1.1.5 {@code value} Classes * @see AccessFlag#IDENTITY * @since 28 @@ -1369,7 +1376,7 @@ private Class elementType() { * {@code true} *

  • its interface modifier is always {@code false}, even when * the component type is an interface - *
  • when preview features are enabled, its {@linkplain + *
  • when preview features are enabled, its {@link * AccessFlag#IDENTITY identity} modifier is always true * * If this {@code Class} object represents a primitive type or @@ -1379,9 +1386,40 @@ private Class elementType() { * arrays, the values of other modifiers are {@code false} other * than as specified above. * + *
    + *
    + * When preview features are enabled, if this {@code Class} object + * represents a class whose {@code class} file does not use preview + * features or represents an array type, its {@code identity} + * modifier is always true. + *

    + * When preview features are disabled, such a {@code Class} object + * does not have its {@code identity} modifier set. + *

    + *
    + * *

    The modifier encodings are defined in section {@jvms 4.1} * of The Java Virtual Machine Specification. * + * @apiNote + *

    + *
    + * Developers should be aware that the presence of the {@code + * identity} modifier is dependent on whether preview features are + * enabled, a status not accessible to programs. The preferred way + * to check for the identity status is to use {@link #isValue() + * Class.isValue()}. + *

    + * This snippet below checks whether a given {@code Class clazz} + * would have its {@code identity} modifier set when preview + * features are enabled, yet behaves consistently regardless of + * whether preview features are enabled. + * {@snippet lang=java : + * !clazz.isPrimitive() && !clazz.isValue() && !clazz.isInterface() + * } + *

    + *
    + * * @return the {@code int} representing the modifiers for this class * @see java.lang.reflect.Modifier * @see #accessFlags() @@ -1415,6 +1453,37 @@ private Class elementType() { * For {@code Class} objects representing void, primitive types, and * arrays, access flags are absent other than as specified above. * + *
    + *
    + * When preview features are enabled, if this {@code Class} object + * represents a class whose {@code class} file does not use preview + * features or represents an array type, its flags always include + * {@code IDENTITY}. + *

    + * When preview features are disabled, such a {@code Class} object + * does not have the {@code IDENTITY} flag set. + *

    + *
    + * + * @apiNote + *
    + *
    + * Developers should be aware that the presence of the {@code + * IDENTITY} flag is dependent on whether preview features are + * enabled, a status not accessible to programs. The preferred way + * to check for the identity status is to use {@link #isValue() + * Class.isValue()}. + *

    + * This snippet below checks whether a given {@code Class clazz} + * would have its {@code IDENTITY} modifier set when preview + * features are enabled, yet behaves consistently regardless of + * whether preview features are enabled. + * {@snippet lang=java : + * !clazz.isPrimitive() && !clazz.isValue() && !clazz.isInterface() + * } + *

    + *
    + * * @see #getModifiers() * @jvms 4.1 The ClassFile Structure * @jvms 4.7.6 The InnerClasses Attribute diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java index 3ccdc8c663c..72110a15e35 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java @@ -82,6 +82,11 @@ public sealed interface StackMapFrameInfo /** * {@return the expanded unset fields} + *

    + * If a stack map frame in a {@code class} file has a non-empty list of + * unset fields, the {@code class} file must declare it uses preview + * features. The list of unset fields is always empty for a stack map frame + * declared in a {@code class} file that does not use preview features. * * @jvms strict-fields-4.7.4 The {@code StackMapTable} Attribute * @since 28 @@ -107,6 +112,12 @@ public static StackMapFrameInfo of(Label target, /** * {@return a new stack map frame} + *

    + * If a stack map frame in a {@code class} file has a non-empty list of + * unset fields, the {@code class} file must declare it uses preview + * features. The list of unset fields is always empty for a stack map frame + * declared in a {@code class} file that does not use preview features. + * * @param target the location of the frame * @param locals the complete list of frame locals * @param stack the complete frame stack diff --git a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java index c108322027b..63822ef8ada 100644 --- a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java +++ b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java @@ -168,7 +168,13 @@ public enum AccessFlag { /** * The access flag {@code ACC_IDENTITY} with a mask value of * {@value "0x%04x" ClassFile#ACC_IDENTITY}. + *

    + * If a class does not use preview features, the {@code ACC_IDENTITY} flag + * is considered always set for that class; if an interface or module + * descriptor does not use preview features, the {@code ACC_IDENTITY} flag + * is considered not set for that interface or module descriptor. * + * @see Class#isValue() * @jvms value-objects-4.1 Class access and property modifiers * @since 28 */ @@ -280,6 +286,10 @@ public enum AccessFlag { * The access flag {@code ACC_STRICT_INIT}, with a mask value of * {@value "0x%04x" ClassFile#ACC_STRICT_INIT}. * + *

    The {@code ACC_STRICT_INIT} flag is considered not set for a field + * declared in a class or interface that does not use preview features. + * + * @see Field#isStrictInit() * @jvms strict-fields-4.5 Field access and property flags * @since 28 */ diff --git a/src/java.base/share/classes/java/lang/reflect/Field.java b/src/java.base/share/classes/java/lang/reflect/Field.java index 84113a51a1e..4cac07f52cb 100644 --- a/src/java.base/share/classes/java/lang/reflect/Field.java +++ b/src/java.base/share/classes/java/lang/reflect/Field.java @@ -285,11 +285,12 @@ public boolean isSynthetic() { * Returns {@code true} if this field is a strictly-initialized field; * returns {@code false} otherwise. * - *

    This method returns {@code true} if and only if preview features are - * enabled and this field is a strictly-initialized field. The - * {@link AccessFlag#STRICT_INIT ACC_STRICT_INIT} flag is considered not set - * when preview features are disabled; consequently, this method always - * returns {@code false} when preview features are disabled. + *

    This method returns {@code true} if and only if the class or interface + * that declares this field uses preview features and this field is a + * strictly-initialized field. The {@link AccessFlag#STRICT_INIT + * ACC_STRICT_INIT} flag is considered not set for a field declared in a + * class or interface that does not use preview features; consequently, + * this method always returns {@code false} when preview features are disabled. * * @return {@code true} if and only if this field is a strictly-initialized * field, as defined by the Java Virtual Machine Specification diff --git a/src/java.base/share/classes/java/util/Objects.java b/src/java.base/share/classes/java/util/Objects.java index cca9b5691e5..c8cd7d428b9 100644 --- a/src/java.base/share/classes/java/util/Objects.java +++ b/src/java.base/share/classes/java/util/Objects.java @@ -196,6 +196,12 @@ public static String toIdentityString(Object o) { * {@code false}. All other objects, including arrays, are identity objects * and the result will be {@code true}. * + *

    This method returns {@code false} if and only if the parameter is + * {@code null} or if the parameter represents a value object when preview + * features are enabled. Value objects do not exist when preview features + * are disabled; consequently, this method behaves the same as {@link + * #nonNull Objects.nonNull} when preview features are disabled. + * * @apiNote * If the parameter is {@code null}, there is no object * and hence no identity; the result is {@code false}. @@ -215,6 +221,12 @@ public static boolean hasIdentity(Object obj) { /** * Checks that the specified object reference is an identity object. + *

    + * This method throws an {@code IdentityException} if and only if the + * parameter represents a value object when preview features are enabled. + * Value objects do not exist when preview features are disabled; + * consequently, this method behaves the same as {@link #requireNonNull(Object) + * Objects.requireNonNull} when preview features are disabled. * * @param obj the object reference to check for identity * @param the type of the reference @@ -223,7 +235,7 @@ public static boolean hasIdentity(Object obj) { * @throws IdentityException if {@code obj} is not an identity object * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS) + @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective = true) @ForceInline public static T requireIdentity(T obj) { Objects.requireNonNull(obj); @@ -234,6 +246,12 @@ public static T requireIdentity(T obj) { /** * Checks that the specified object reference is an identity object. + *

    + * This method throws an {@code IdentityException} if and only if the + * parameter represents a value object when preview features are enabled. + * Value objects do not exist when preview features are disabled; + * consequently, this method behaves the same as {@link #requireNonNull(Object, String) + * Objects.requireNonNull} when preview features are disabled. * * @param obj the object reference to check for identity * @param message detail message to be used in the event that an @@ -244,7 +262,7 @@ public static T requireIdentity(T obj) { * @throws IdentityException if {@code obj} is not an identity object * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS) + @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective = true) @ForceInline public static T requireIdentity(T obj, String message) { Objects.requireNonNull(obj); @@ -255,6 +273,12 @@ public static T requireIdentity(T obj, String message) { /** * Checks that the specified object reference is an identity object. + *

    + * This method throws an {@code IdentityException} if and only if the + * parameter represents a value object when preview features are enabled. + * Value objects do not exist when preview features are disabled; + * consequently, this method behaves the same as {@link #requireNonNull(Object, Supplier) + * Objects.requireNonNull} when preview features are disabled. * * @param obj the object reference to check for identity * @param messageSupplier supplier of the detail message to be @@ -265,7 +289,7 @@ public static T requireIdentity(T obj, String message) { * @throws IdentityException if {@code obj} is not an identity object * @since 28 */ - @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS) + @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective = true) @ForceInline public static T requireIdentity(T obj, Supplier messageSupplier) { Objects.requireNonNull(obj);