< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

*** 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;

*** 228,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 {
          registerNatives();
      }
--- 229,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 {
          registerNatives();
      }

*** 316,18 ***
--- 317,23 ---
                  } 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(' ');
                  }
  
                  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");

*** 630,10 ***
--- 636,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)
+     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)
+     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.

*** 1421,13 ***
       * @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}
       *
       * <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
--- 1460,14 ---
       * @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

*** 1453,33 ***
          // 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);
      }
  
!     /**
       * 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 native Object[] getSigners();
  
- 
      /**
       * Set the signers of this class.
       */
      native void setSigners(Object[] signers);
  
- 
      /**
       * If this {@code Class} object represents a local or anonymous
       * class within a method, returns a {@link
       * java.lang.reflect.Method Method} object representing the
       * immediately enclosing method of the underlying class. Returns
--- 1493,38 ---
          // Use getClassAccessFlagsRaw to expose SUPER status.
          var location = (isMemberClass() || isLocalClass() ||
                          isAnonymousClass() || isArray()) ?
              AccessFlag.Location.INNER_CLASS :
              AccessFlag.Location.CLASS;
!         int accessFlags = (location == AccessFlag.Location.CLASS) ?
!                 getClassAccessFlagsRaw() : getModifiers();
!         var cffv = ClassFileFormatVersion.fromMajor(getClassFileVersion() & 0xffff);
!         if (cffv.compareTo(ClassFileFormatVersion.latest()) >= 0) {
+             // Ignore unspecified (0x0800) access flag for current version
+             accessFlags &= ~0x0800;
+         }
+         if (!PreviewFeatures.isEnabled() && location == AccessFlag.Location.INNER_CLASS) {
+             accessFlags &= ~Modifier.IDENTITY; // drop ACC_IDENTITY bit in inner class if not in preview
+         }
+         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 native Object[] getSigners();
  
      /**
       * Set the signers of this class.
       */
      native void setSigners(Object[] signers);
  
      /**
       * If this {@code Class} object represents a local or anonymous
       * class within a method, returns a {@link
       * java.lang.reflect.Method Method} object representing the
       * immediately enclosing method of the underlying class. Returns

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

*** 4802,11 ***
       *
       * 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() {
          Class<?> c = isArray() ? elementType() : this;
          return c.getClassFileVersion0();
      }
  
      private native int getClassFileVersion0();
--- 4847,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.
       */
!     /* package-private */
+     int getClassFileVersion() {
          Class<?> c = isArray() ? elementType() : this;
          return c.getClassFileVersion0();
      }
  
      private native int getClassFileVersion0();
< prev index next >