< prev index next >

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

Print this page
*** 76,10 ***
--- 76,11 ---
  import jdk.internal.reflect.CallerSensitive;
  import jdk.internal.reflect.CallerSensitiveAdapter;
  import jdk.internal.reflect.ConstantPool;
  import jdk.internal.reflect.Reflection;
  import jdk.internal.reflect.ReflectionFactory;
+ import jdk.internal.value.PrimitiveClass;
  import jdk.internal.vm.annotation.ForceInline;
  import jdk.internal.vm.annotation.IntrinsicCandidate;
  import sun.invoke.util.Wrapper;
  import sun.reflect.generics.factory.CoreReflectionFactory;
  import sun.reflect.generics.factory.GenericsFactory;

*** 198,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();
      }
--- 199,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();
      }

*** 232,12 ***
       * this method returns "class " followed by {@code getName}.
       *
       * @return a string representation of this {@code Class} object.
       */
      public String toString() {
!         String kind = isInterface() ? "interface " : isPrimitive() ? "" : "class ";
!         return kind.concat(getName());
      }
  
      /**
       * Returns a string describing this {@code Class}, including
       * information about modifiers and type parameters.
--- 233,26 ---
       * this method returns "class " followed by {@code getName}.
       *
       * @return a string representation of this {@code Class} object.
       */
      public String toString() {
!         String s = getName();
!         if (isPrimitive()) {
+             return s;
+         }
+         // Avoid invokedynamic based String concat, might be not available
+         // Prepend type of class
+         s = (isInterface() ? "interface " : "class ").concat(s);
+         if (isValue()) {
+             // prepend value class type
+             s = (isPrimitiveClass() ? "primitive " : "value ").concat(s);
+             if (isPrimitiveClass() && isPrimaryType()) {
+                 // Append .ref
+                 s = s.concat(".ref");
+             }
+         }
+         return s;
      }
  
      /**
       * Returns a string describing this {@code Class}, including
       * information about modifiers and type parameters.

*** 286,18 ***
--- 301,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(isPrimitiveClass() ? "primitive " : "value ");
+                 }
                  if (isInterface()) { // Note: all annotation interfaces are interfaces
                      sb.append("interface");
                  } else {
                      if (isEnum())
                          sb.append("enum");

*** 496,12 ***
          return forName0(name, initialize, loader, caller);
      }
  
      /** Called after security check for system loader access checks have been made. */
      private static native Class<?> forName0(String name, boolean initialize,
!                                             ClassLoader loader,
!                                             Class<?> caller)
          throws ClassNotFoundException;
  
  
      /**
       * Returns the {@code Class} with the given <a href="ClassLoader.html#binary-name">
--- 516,12 ---
          return forName0(name, initialize, loader, caller);
      }
  
      /** Called after security check for system loader access checks have been made. */
      private static native Class<?> forName0(String name, boolean initialize,
!                                     ClassLoader loader,
!                                     Class<?> caller)
          throws ClassNotFoundException;
  
  
      /**
       * Returns the {@code Class} with the given <a href="ClassLoader.html#binary-name">

*** 586,10 ***
--- 606,138 ---
          } else {
              return BootLoader.loadClass(module, name);
          }
      }
  
+     // set by VM if this class is an exotic type such as primitive class
+     // otherwise, these two fields are null
+     private transient Class<T> primaryType;
+     private transient Class<T> secondaryType;
+ 
+     /**
+      * Returns {@code true} if this class is a primitive class.
+      * <p>
+      * Each primitive class has a {@linkplain #isPrimaryType() primary type}
+      * representing the <em>primitive reference type</em> and a
+      * {@linkplain #isPrimitiveValueType() secondary type} representing
+      * the <em>primitive value type</em>.  The primitive reference type
+      * and primitive value type can be obtained by calling the
+      * {@link #asPrimaryType()} and {@link #asValueType} method
+      * of a primitive class respectively.
+      * <p>
+      * A primitive class is a {@linkplain #isValue() value class}.
+      *
+      * @return {@code true} if this class is a primitive class, otherwise {@code false}
+      * @see #isValue()
+      * @see #asPrimaryType()
+      * @see #asValueType()
+      * @since Valhalla
+      */
+     /* package */ boolean isPrimitiveClass() {
+         return (this.getModifiers() & PrimitiveClass.PRIMITIVE_CLASS) != 0;
+     }
+ 
+     /**
+      * {@return {@code true} if this class is an identity class, otherwise {@code false}}
+      *
+      * @since Valhalla
+      */
+     public boolean isIdentity() {
+         return (this.getModifiers() & Modifier.IDENTITY) != 0;
+     }
+ 
+     /**
+      * {@return {@code true} if this class is a value class, otherwise {@code false}}
+      *
+      * @since Valhalla
+      */
+     public boolean isValue() {
+         return (this.getModifiers() & Modifier.VALUE) != 0;
+     }
+ 
+     /**
+      * Returns a {@code Class} object representing the primary type
+      * of this class or interface.
+      * <p>
+      * If this {@code Class} object represents a primitive type or an array type,
+      * then this method returns this class.
+      * <p>
+      * If this {@code Class} object represents a {@linkplain #isPrimitiveClass()
+      * primitive class}, then this method returns the <em>primitive reference type</em>
+      * type of this primitive class.
+      * <p>
+      * Otherwise, this {@code Class} object represents a non-primitive class or interface
+      * and this method returns this class.
+      *
+      * @return the {@code Class} representing the primary type of
+      *         this class or interface
+      * @since Valhalla
+      */
+     @IntrinsicCandidate
+     /* package */ Class<?> asPrimaryType() {
+         return isPrimitiveClass() ? primaryType : this;
+     }
+ 
+     /**
+      * Returns a {@code Class} object representing the <em>primitive value type</em>
+      * of this class if this class is a {@linkplain #isPrimitiveClass() primitive class}.
+      *
+      * @apiNote Alternatively, this method returns null if this class is not
+      *          a primitive class rather than throwing UOE.
+      *
+      * @return the {@code Class} representing the {@linkplain #isPrimitiveValueType()
+      * primitive value type} of this class if this class is a primitive class
+      * @throws UnsupportedOperationException if this class or interface
+      *         is not a primitive class
+      * @since Valhalla
+      */
+     @IntrinsicCandidate
+     /* package */ Class<?> asValueType() {
+         if (isPrimitiveClass())
+             return secondaryType;
+ 
+         throw new UnsupportedOperationException(this.getName().concat(" is not a primitive class"));
+     }
+ 
+     /**
+      * Returns {@code true} if this {@code Class} object represents the primary type
+      * of this class or interface.
+      * <p>
+      * If this {@code Class} object represents a primitive type or an array type,
+      * then this method returns {@code true}.
+      * <p>
+      * If this {@code Class} object represents a {@linkplain #isPrimitiveClass()
+      * primitive}, then this method returns {@code true} if this {@code Class}
+      * object represents a primitive reference type, or returns {@code false}
+      * if this {@code Class} object represents a primitive value type.
+      * <p>
+      * If this {@code Class} object represents a non-primitive class or interface,
+      * then this method returns {@code true}.
+      *
+      * @return {@code true} if this {@code Class} object represents
+      * the primary type of this class or interface
+      * @since Valhalla
+      */
+     /* package */ boolean isPrimaryType() {
+         if (isPrimitiveClass()) {
+             return this == primaryType;
+         }
+         return true;
+     }
+ 
+     /**
+      * Returns {@code true} if this {@code Class} object represents
+      * a {@linkplain #isPrimitiveClass() primitive} value type.
+      *
+      * @return {@code true} if this {@code Class} object represents
+      * the value type of a primitive class
+      * @since Valhalla
+      */
+     /* package */ boolean isPrimitiveValueType() {
+         return isPrimitiveClass() && this == secondaryType;
+     }
+ 
      /**
       * Creates a new instance of the class represented by this {@code Class}
       * object.  The class is instantiated as if by a {@code new}
       * expression with an empty argument list.  The class is initialized if it
       * has not already been initialized.

*** 730,21 ***
       * Determines if the class or interface represented by this
       * {@code Class} object is either the same as, or is a superclass or
       * superinterface of, the class or interface represented by the specified
       * {@code Class} parameter. It returns {@code true} if so;
       * otherwise it returns {@code false}. If this {@code Class}
       * object represents a primitive type, this method returns
       * {@code true} if the specified {@code Class} parameter is
       * exactly this {@code Class} object; otherwise it returns
       * {@code false}.
       *
       * <p> Specifically, this method tests whether the type represented by the
       * specified {@code Class} parameter can be converted to the type
       * represented by this {@code Class} object via an identity conversion
!      * or via a widening reference conversion. See <cite>The Java Language
!      * Specification</cite>, sections {@jls 5.1.1} and {@jls 5.1.4},
!      * for details.
       *
       * @param     cls the {@code Class} object to be checked
       * @return    the {@code boolean} value indicating whether objects of the
       *            type {@code cls} can be assigned to objects of this class
       * @throws    NullPointerException if the specified Class parameter is
--- 878,25 ---
       * Determines if the class or interface represented by this
       * {@code Class} object is either the same as, or is a superclass or
       * superinterface of, the class or interface represented by the specified
       * {@code Class} parameter. It returns {@code true} if so;
       * otherwise it returns {@code false}. If this {@code Class}
+      * object represents the {@linkplain #isPrimaryType() reference type}
+      * of a {@linkplain #isPrimitiveClass() primitive class}, this method
+      * return {@code true} if the specified {@code Class} parameter represents
+      * the same primitive class. If this {@code Class}
       * object represents a primitive type, this method returns
       * {@code true} if the specified {@code Class} parameter is
       * exactly this {@code Class} object; otherwise it returns
       * {@code false}.
       *
       * <p> Specifically, this method tests whether the type represented by the
       * specified {@code Class} parameter can be converted to the type
       * represented by this {@code Class} object via an identity conversion
!      * or via a widening reference conversion or via a primitive widening
!      * conversion. See <cite>The Java Language Specification</cite>,
!      * sections {@jls 5.1.1} and {@jls 5.1.4}, for details.
       *
       * @param     cls the {@code Class} object to be checked
       * @return    the {@code boolean} value indicating whether objects of the
       *            type {@code cls} can be assigned to objects of this class
       * @throws    NullPointerException if the specified Class parameter is

*** 1293,10 ***
--- 1445,12 ---
       * in an integer. The modifiers consist of the Java Virtual Machine's
       * constants for {@code public}, {@code protected},
       * {@code private}, {@code final}, {@code static},
       * {@code abstract} and {@code interface}; they should be decoded
       * using the methods of class {@code Modifier}.
+      * The modifiers also include the Java Virtual Machine's constants for
+      * {@code identity class} and {@code value class}.
       *
       * <p> If the underlying class is an array class, then its
       * {@code public}, {@code private} and {@code protected}
       * modifiers are the same as those of its component type.  If this
       * {@code Class} object represents a primitive type or void, its

*** 1322,11 ***
       * @jls 9.1.1. Interface Modifiers
       */
      @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, then its
       * {@code PUBLIC}, {@code PRIVATE} and {@code PROTECTED}
--- 1476,11 ---
       * @jls 9.1.1. Interface Modifiers
       */
      @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, then its
       * {@code PUBLIC}, {@code PRIVATE} and {@code PROTECTED}

*** 1358,27 ***
                                              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
--- 1512,25 ---
                                              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

*** 1756,14 ***
                  int dimensions = 0;
                  do {
                      dimensions++;
                      cl = cl.getComponentType();
                  } while (cl.isArray());
!                 return cl.getName().concat("[]".repeat(dimensions));
              } catch (Throwable e) { /*FALLTHRU*/ }
          }
!         return getName();
      }
  
      /**
       * Returns the canonical name of the underlying class as
       * defined by <cite>The Java Language Specification</cite>.
--- 1908,19 ---
                  int dimensions = 0;
                  do {
                      dimensions++;
                      cl = cl.getComponentType();
                  } while (cl.isArray());
!                 return cl.getTypeName().concat("[]".repeat(dimensions));
              } catch (Throwable e) { /*FALLTHRU*/ }
          }
!         if (isPrimitiveClass()) {
+             // TODO: null-default
+             return isPrimaryType() ? getName().concat(".ref") : getName();
+         } else {
+             return getName();
+         }
      }
  
      /**
       * Returns the canonical name of the underlying class as
       * defined by <cite>The Java Language Specification</cite>.

*** 3977,10 ***
--- 4134,13 ---
       * @since 1.5
       */
      @SuppressWarnings("unchecked")
      @IntrinsicCandidate
      public T cast(Object obj) {
+         if (isPrimitiveValueType() && obj == null)
+             throw new NullPointerException(getName() + " is a primitive value type");
+ 
          if (obj != null && !isInstance(obj))
              throw new ClassCastException(cannotCastMsg(obj));
          return (T) obj;
      }
  

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

*** 4487,24 ***
          if (isPrimitive())
              return Wrapper.forPrimitiveType(this).basicTypeString();
  
          if (isArray()) {
              return "[" + componentType.descriptorString();
!         } else if (isHidden()) {
              String name = getName();
              int index = name.indexOf('/');
              return new StringBuilder(name.length() + 2)
!                     .append('L')
                      .append(name.substring(0, index).replace('.', '/'))
                      .append('.')
                      .append(name, index + 1, name.length())
                      .append(';')
                      .toString();
          } else {
              String name = getName().replace('.', '/');
              return new StringBuilder(name.length() + 2)
!                     .append('L')
                      .append(name)
                      .append(';')
                      .toString();
          }
      }
--- 4647,26 ---
          if (isPrimitive())
              return Wrapper.forPrimitiveType(this).basicTypeString();
  
          if (isArray()) {
              return "[" + componentType.descriptorString();
!         }
+         char typeDesc = isPrimitiveValueType() ? 'Q' : 'L';
+         if (isHidden()) {
              String name = getName();
              int index = name.indexOf('/');
              return new StringBuilder(name.length() + 2)
!                     .append(typeDesc)
                      .append(name.substring(0, index).replace('.', '/'))
                      .append('.')
                      .append(name, index + 1, name.length())
                      .append(';')
                      .toString();
          } else {
              String name = getName().replace('.', '/');
              return new StringBuilder(name.length() + 2)
!                     .append(typeDesc)
                      .append(name)
                      .append(';')
                      .toString();
          }
      }
< prev index next >