< prev index next >

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

Print this page
@@ -37,10 +37,11 @@
  import java.io.ObjectStreamField;
  import java.lang.reflect.AnnotatedElement;
  import java.lang.reflect.AnnotatedType;
  import java.lang.reflect.AccessFlag;
  import java.lang.reflect.Array;
+ import java.lang.reflect.ClassFileFormatVersion;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Executable;
  import java.lang.reflect.Field;
  import java.lang.reflect.GenericArrayType;
  import java.lang.reflect.GenericDeclaration;

@@ -223,13 +224,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 final int ANNOTATION = 0x00002000;
+     private static final int ENUM       = 0x00004000;
+     private static final int SYNTHETIC  = 0x00001000;
  
      private static native void registerNatives();
      static {
          registerNatives();
      }

@@ -312,10 +313,12 @@
                  } while (component.isArray());
                  sb.append(component.getName());
              } else {
                  // Class modifiers are a superset of interface modifiers
                  int modifiers = getModifiers() & Modifier.classModifiers();
+                 // Modifier.toString() below mis-interprets SYNCHRONIZED, STRICT, and VOLATILE bits
+                 modifiers &= ~(Modifier.SYNCHRONIZED | Modifier.STRICT | Modifier.VOLATILE);
                  if (modifiers != 0) {
                      sb.append(Modifier.toString(modifiers));
                      sb.append(' ');
                  }
  

@@ -325,10 +328,13 @@
                  addSealingInfo(modifiers, sb);
  
                  if (isAnnotation()) {
                      sb.append('@');
                  }
+                 if (isValue()) {
+                     sb.append("value ");
+                 }
                  if (isInterface()) { // Note: all annotation interfaces are interfaces
                      sb.append("interface");
                  } else {
                      if (isEnum())
                          sb.append("enum");

@@ -674,10 +680,43 @@
          } else {
              return BootLoader.loadClass(module, name);
          }
      }
  
+     /**
+      * {@return {@code true} if this {@code Class} object represents an identity
+      * class or interface; otherwise {@code false}}
+      *
+      * If this {@code Class} object represents an array type, then this method
+      * returns {@code true}.
+      * If this {@code Class} object represents a primitive type, or {@code void},
+      * then this method returns {@code false}.
+      *
+      * @since Valhalla
+      */
+     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
+     public native boolean isIdentity();
+ 
+     /**
+      * {@return {@code true} if this {@code Class} object represents a value
+      * class; otherwise {@code false}}
+      *
+      * If this {@code Class} object represents an array type, an interface,
+      * a primitive type, or {@code void}, then this method returns {@code false}.
+      *
+      * @since Valhalla
+      */
+     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
+     public boolean isValue() {
+         if (!PreviewFeatures.isEnabled()) {
+             return false;
+         }
+          if (isPrimitive() || isArray() || isInterface())
+              return false;
+         return ((getModifiers() & Modifier.IDENTITY) == 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.

@@ -1440,10 +1479,11 @@
       *      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> its {@code 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

@@ -1465,21 +1505,23 @@
       * @jvms 4.1 The {@code ClassFile} Structure
       */
      @IntrinsicCandidate
      public native int getModifiers();
  
-     /**
+    /**
       * {@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> its {@code identity} modifier is always true
       * </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

@@ -1497,24 +1539,32 @@
          // Use getClassAccessFlagsRaw to expose SUPER status.
          var location = (isMemberClass() || isLocalClass() ||
                          isAnonymousClass() || isArray()) ?
              AccessFlag.Location.INNER_CLASS :
              AccessFlag.Location.CLASS;
-         return AccessFlag.maskToAccessFlags((location == AccessFlag.Location.CLASS) ?
-                                             getClassAccessFlagsRaw() :
-                                             getModifiers(),
-                                             location);
+         int accessFlags = (location == AccessFlag.Location.CLASS) ?
+                 getClassAccessFlagsRaw() : getModifiers();
+         if (isArray() && PreviewFeatures.isEnabled()) {
+             accessFlags |= Modifier.IDENTITY;
+         }
+         var cffv = ClassFileFormatVersion.fromMajor(getClassFileVersion() & 0xffff);
+         if (cffv.compareTo(ClassFileFormatVersion.latest()) >= 0) {
+             // Ignore unspecified (0x0800) access flag for current version
+             accessFlags &= ~0x0800;
+         }
+         return AccessFlag.maskToAccessFlags(accessFlags, location, cffv);
      }
  
-     /**
+    /**
       * Gets the signers of this class.
       *
       * @return  the signers of this class, or null if there are no signers.  In
       *          particular, this method returns null if this {@code Class} object represents
       *          a primitive type or void.
       * @since   1.1
       */
+ 
      public Object[] getSigners() {
          var signers = this.signers;
          return signers == null ? null : signers.clone();
      }
  

@@ -4437,11 +4487,11 @@
       *
       * @return an array representing the superinterfaces
       * @since 1.8
       */
      public AnnotatedType[] getAnnotatedInterfaces() {
-          return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
+         return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
      }
  
      private native Class<?> getNestHost0();
  
      /**

@@ -4835,11 +4885,12 @@
       *
       * If the class is an array type then the class file version of its element
       * type is returned.  If the class is a primitive type then the latest class
       * file major version is returned and zero is returned for the minor version.
       */
-     private int getClassFileVersion() {
+     /* package-private */
+     int getClassFileVersion() {
          Class<?> c = isArray() ? elementType() : this;
          return c.getClassFileVersion0();
      }
  
      private native int getClassFileVersion0();
< prev index next >