< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page
*** 50,10 ***
--- 50,11 ---
  import java.lang.reflect.Modifier;
  import java.lang.reflect.RecordComponent;
  import java.lang.reflect.Type;
  import java.lang.reflect.TypeVariable;
  import java.lang.constant.Constable;
+ import java.lang.classfile.ClassFile;
  import java.net.URL;
  import java.security.AllPermission;
  import java.security.Permissions;
  import java.security.ProtectionDomain;
  import java.util.ArrayList;

*** 68,17 ***
--- 69,21 ---
  import java.util.Optional;
  import java.util.Set;
  import java.util.stream.Collectors;
  
  import jdk.internal.constant.ConstantUtils;
+ import jdk.internal.javac.PreviewFeature;
  import jdk.internal.loader.BootLoader;
  import jdk.internal.loader.BuiltinClassLoader;
+ import jdk.internal.misc.PreviewFeatures;
  import jdk.internal.misc.Unsafe;
  import jdk.internal.module.Resources;
+ import jdk.internal.reflect.AccessFlagSet;
  import jdk.internal.reflect.CallerSensitive;
  import jdk.internal.reflect.CallerSensitiveAdapter;
  import jdk.internal.reflect.ConstantPool;
+ import jdk.internal.reflect.PreviewAccessFlags;
  import jdk.internal.reflect.Reflection;
  import jdk.internal.reflect.ReflectionFactory;
  import jdk.internal.util.ModifiedUtf;
  import jdk.internal.vm.annotation.AOTRuntimeSetup;
  import jdk.internal.vm.annotation.AOTSafeClassInitializer;

*** 222,13 ***
                                GenericDeclaration,
                                Type,
                                AnnotatedElement,
                                TypeDescriptor.OfField<Class<?>>,
                                Constable {
-     private static final int ANNOTATION = 0x00002000;
-     private static final int ENUM       = 0x00004000;
-     private static final int SYNTHETIC  = 0x00001000;
  
      private static native void registerNatives();
      static {
          runtimeSetup();
      }
--- 227,10 ---

*** 342,14 ***
                  if (isInterface()) { // Note: all annotation interfaces are interfaces
                      sb.append("interface");
                  } else {
                      if (isEnum())
                          sb.append("enum");
!                     else if (isRecord())
!                         sb.append("record");
!                     else
!                         sb.append("class");
                  }
                  sb.append(' ');
                  sb.append(getName());
              }
  
--- 344,19 ---
                  if (isInterface()) { // Note: all annotation interfaces are interfaces
                      sb.append("interface");
                  } else {
                      if (isEnum())
                          sb.append("enum");
!                     else {
!                         if (isValue()) {
!                             sb.append("value ");
!                         }
+                         if (isRecord())
+                             sb.append("record");
+                         else
+                             sb.append("class");
+                     }
                  }
                  sb.append(' ');
                  sb.append(getName());
              }
  

*** 614,10 ***
--- 621,32 ---
          } else {
              return BootLoader.loadClass(module, name);
          }
      }
  
+     /**
+      * {@return {@code true} if this {@code Class} object represents a value class,
+      * otherwise {@code false}}
+      *
+      * <p>A value class is declared with the {@code value} modifier. If this
+      * {@code Class} object represents an interface, array type, primitive type,
+      * or {@code void}, the result is {@code false}.
+      *
+      * @jls value-objects-8.1.1.5 {@code value} Classes
+      * @see AccessFlag#IDENTITY
+      * @since Valhalla
+      */
+     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
+     public boolean isValue() {
+         if (!PreviewFeatures.isEnabled()) {
+             return false;
+         } else {
+             int mask = ClassFile.ACC_IDENTITY | ClassFile.ACC_INTERFACE;
+             return !primitive && (getModifiers() & mask) == 0;
+         }
+     }
+ 
      /**
       * {@return the {@code Class} object associated with the
       * {@linkplain #isPrimitive() primitive type} of the given name}
       * If the argument is not the name of a primitive type, {@code
       * null} is returned.

*** 869,11 ***
       * @return {@code true} if this {@code Class} object represents an annotation
       *      interface; {@code false} otherwise
       * @since 1.5
       */
      public boolean isAnnotation() {
!         return (getModifiers() & ANNOTATION) != 0;
      }
  
      /**
       *{@return {@code true} if and only if this class has the synthetic modifier
       * bit set}
--- 898,11 ---
       * @return {@code true} if this {@code Class} object represents an annotation
       *      interface; {@code false} otherwise
       * @since 1.5
       */
      public boolean isAnnotation() {
!         return (getModifiers() & ClassFile.ACC_ANNOTATION) != 0;
      }
  
      /**
       *{@return {@code true} if and only if this class has the synthetic modifier
       * bit set}

*** 884,11 ***
       * href="{@docRoot}/java.base/java/lang/reflect/package-summary.html#LanguageJvmModel">Java
       * programming language and JVM modeling in core reflection</a>
       * @since 1.5
       */
      public boolean isSynthetic() {
!         return (getModifiers() & SYNTHETIC) != 0;
      }
  
      /**
       * Returns the  name of the entity (class, interface, array class,
       * primitive type, or void) represented by this {@code Class} object.
--- 913,11 ---
       * href="{@docRoot}/java.base/java/lang/reflect/package-summary.html#LanguageJvmModel">Java
       * programming language and JVM modeling in core reflection</a>
       * @since 1.5
       */
      public boolean isSynthetic() {
!         return (getModifiers() & ClassFile.ACC_SYNTHETIC) != 0;
      }
  
      /**
       * Returns the  name of the entity (class, interface, array class,
       * primitive type, or void) represented by this {@code Class} object.

*** 1017,11 ***
  
      private transient Object classData; // Set by VM
      private transient Object[] signers; // Read by VM, mutable
      private final transient char modifiers;  // Set by the VM
      private final transient char classFileAccessFlags;  // Set by the VM
!     private final transient boolean primitive;  // Set by the VM if the Class is a primitive type.
  
      // package-private
      Object getClassData() {
          return classData;
      }
--- 1046,11 ---
  
      private transient Object classData; // Set by VM
      private transient Object[] signers; // Read by VM, mutable
      private final transient char modifiers;  // Set by the VM
      private final transient char classFileAccessFlags;  // Set by the VM
!     private final transient boolean primitive;  // Set by the VM if the Class is a primitive type
  
      // package-private
      Object getClassData() {
          return classData;
      }

*** 1337,10 ***
--- 1366,12 ---
       *      modifiers are the same as those of its component type
       * <li> its {@code abstract} and {@code final} modifiers are always
       *      {@code true}
       * <li> its interface modifier is always {@code false}, even when
       *      the component type is an interface
+      * <li> when preview features are enabled, its {@linkplain
+      *      AccessFlag#IDENTITY identity} modifier is always true
       * </ul>
       * If this {@code Class} object represents a primitive type or
       * void, its {@code public}, {@code abstract}, and {@code final}
       * modifiers are always {@code true}.
       * For {@code Class} objects representing void, primitive types, and

*** 1364,18 ***
--- 1395,21 ---
      public int getModifiers() { return modifiers; }
  
      /**
       * {@return an unmodifiable set of the {@linkplain AccessFlag access
       * flags} for this class, possibly empty}
+      * The {@code AccessFlags} may depend on the class file format version of the class.
       *
       * <p> If the underlying class is an array class:
       * <ul>
       * <li> its {@code PUBLIC}, {@code PRIVATE} and {@code PROTECTED}
       *      access flags are the same as those of its component type
       * <li> its {@code ABSTRACT} and {@code FINAL} flags are present
       * <li> its {@code INTERFACE} flag is absent, even when the
       *      component type is an interface
+      * <li> when preview features are enabled, its {@code IDENTITY} flag
+     *       is present
       * </ul>
       * If this {@code Class} object represents a primitive type or
       * void, the flags are {@code PUBLIC}, {@code ABSTRACT}, and
       * {@code FINAL}.
       * For {@code Class} objects representing void, primitive types, and

*** 1385,21 ***
       * @jvms 4.1 The ClassFile Structure
       * @jvms 4.7.6 The InnerClasses Attribute
       * @since 20
       */
      public Set<AccessFlag> accessFlags() {
!         // Location.CLASS allows SUPER and AccessFlag.MODULE which
!         // INNER_CLASS forbids. INNER_CLASS allows PRIVATE, PROTECTED,
!         // and STATIC, which are not allowed on Location.CLASS.
!         // Use getClassFileAccessFlags to expose SUPER status.
!         // Arrays need to use PRIVATE/PROTECTED from its component modifiers.
!         var location = (isMemberClass() || isLocalClass() ||
!                         isAnonymousClass() || isArray()) ?
!             AccessFlag.Location.INNER_CLASS :
!             AccessFlag.Location.CLASS;
!         return getReflectionFactory().parseAccessFlags((location == AccessFlag.Location.CLASS) ?
!                         getClassFileAccessFlags() : getModifiers(), location, this);
      }
  
      /**
       * Gets the signers of this class.
       *
--- 1419,24 ---
       * @jvms 4.1 The ClassFile Structure
       * @jvms 4.7.6 The InnerClasses Attribute
       * @since 20
       */
      public Set<AccessFlag> accessFlags() {
!         if (!PreviewFeatures.isEnabled()) {
!             // INNER_CLASS_FLAGS exclusively defines PRIVATE, PROTECTED, and STATIC.
!             // CLASS_FLAGS exclusively defines SUPER and MODULE.
!             // Nested classes and interfaces need to report PRIVATE/PROTECTED/STATIC.
!             // Arrays need to report PRIVATE/PROTECTED.
!             // Top-level classes need to report SUPER, using getClassFileAccessFlags.
!             // Module descriptors do not have Class objects so nothing reports MODULE.
!             return (isArray() || getEnclosingClass() != null)
!                     ? AccessFlagSet.ofValidated(AccessFlagSet.INNER_CLASS_FLAGS, getModifiers())
!                     : AccessFlagSet.ofValidated(AccessFlagSet.CLASS_FLAGS, getClassFileAccessFlags());
!         }
+         // CLASS_FLAGS exclusively defines MODULE, but module descriptors are
+         // never represented with Class objects, so INNER_CLASS_FLAGS works
+         return AccessFlagSet.ofValidated(PreviewAccessFlags.INNER_CLASS_PREVIEW_FLAGS, getModifiers());
      }
  
      /**
       * Gets the signers of this class.
       *

*** 3360,11 ***
       */
      public boolean isEnum() {
          // An enum must both directly extend java.lang.Enum and have
          // the ENUM bit set; classes for specialized enum constants
          // don't do the former.
!         return (this.getModifiers() & ENUM) != 0 &&
          this.getSuperclass() == java.lang.Enum.class;
      }
  
      /**
       * Returns {@code true} if and only if this class is a record class.
--- 3397,11 ---
       */
      public boolean isEnum() {
          // An enum must both directly extend java.lang.Enum and have
          // the ENUM bit set; classes for specialized enum constants
          // don't do the former.
!         return (this.getModifiers() & ClassFile.ACC_ENUM) != 0 &&
          this.getSuperclass() == java.lang.Enum.class;
      }
  
      /**
       * Returns {@code true} if and only if this class is a record class.
< prev index next >