< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 1994, 2025, 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, 2026, 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

*** 68,17 ***
--- 68,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;

*** 243,19 ***
      /*
       * Private constructor. Only the Java Virtual Machine creates Class objects.
       * This constructor is not used and prevents the default constructor being
       * generated.
       */
!     private Class(ClassLoader loader, Class<?> arrayComponentType, char mods, ProtectionDomain pd, boolean isPrim, char flags) {
          // Initialize final field for classLoader.  The initialization value of non-null
          // prevents future JIT optimizations from assuming this final field is null.
          // The following assignments are done directly by the VM without calling this constructor.
          classLoader = loader;
          componentType = arrayComponentType;
          modifiers = mods;
          protectionDomain = pd;
          primitive = isPrim;
          classFileAccessFlags = flags;
      }
  
      /**
       * Converts the object to a string. The string representation is the
--- 247,20 ---
      /*
       * Private constructor. Only the Java Virtual Machine creates Class objects.
       * This constructor is not used and prevents the default constructor being
       * generated.
       */
!     private Class(ClassLoader loader, Class<?> arrayComponentType, char mods, ProtectionDomain pd, boolean isPrim, boolean isIdentity, char flags) {
          // Initialize final field for classLoader.  The initialization value of non-null
          // prevents future JIT optimizations from assuming this final field is null.
          // The following assignments are done directly by the VM without calling this constructor.
          classLoader = loader;
          componentType = arrayComponentType;
          modifiers = mods;
          protectionDomain = pd;
          primitive = isPrim;
+         identity = isIdentity;
          classFileAccessFlags = flags;
      }
  
      /**
       * Converts the object to a string. The string representation is the

*** 323,10 ***
--- 328,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(' ');
                  }
  

*** 341,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());
              }
  
--- 348,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());
              }
  

*** 613,10 ***
--- 625,58 ---
          } else {
              return BootLoader.loadClass(module, name);
          }
      }
  
+     /**
+      * {@return {@code true} if this {@code Class} object represents an identity class,
+      * otherwise {@code false}}
+      *
+      * <ul>
+      *      <li>
+      *          If this {@code Class} object represents an array type this method returns {@code true}.
+      *      <li>
+      *          If this {@code Class} object represents an interface, a primitive type,
+      *          or {@code void} this method returns {@code false}.
+      *      <li>
+      *          For all other {@code Class} objects, this method returns {@code true} if either
+      *          preview features are disabled or {@linkplain AccessFlag#IDENTITY IDENTITY} is
+      *          present in the {@linkplain #accessFlags() class access flags}.
+      * </ul>
+      * @see AccessFlag#IDENTITY
+      * @since Valhalla
+      */
+     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
+     public boolean isIdentity() {
+         return identity;
+     }
+ 
+     /**
+      * {@return {@code true} if this {@code Class} object represents a value class,
+      * otherwise {@code false}}
+      * <ul>
+      *      <li>
+      *          If this {@code Class} object represents an array type this method returns {@code false}.
+      *      <li>
+      *          If this {@code Class} object represents an interface, a primitive type,
+      *          or {@code void} this method returns {@code true} only if preview features are enabled.
+      *      <li>
+      *          For all other {@code Class} objects, this method returns {@code true} only if
+      *          preview features are enabled and {@linkplain AccessFlag#IDENTITY IDENTITY} is not
+      *          present in the {@linkplain #accessFlags() class access flags}.
+      * </ul>
+      * @see AccessFlag#IDENTITY
+      * @since Valhalla
+      */
+     @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective=true)
+     public boolean isValue() {
+         if (!PreviewFeatures.isEnabled()) {
+             return false;
+         }
+         return !isIdentity();
+     }
+ 
      /**
       * {@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.

*** 1016,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;
      }
--- 1076,12 ---
  
      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
+     private final transient boolean identity;   // Set by the VM if the Class is an identity class
  
      // package-private
      Object getClassData() {
          return classData;
      }

*** 1336,10 ***
--- 1397,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

*** 1363,18 ***
--- 1426,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

*** 1384,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.
       *
--- 1450,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.
       *
< prev index next >