< prev index next >

src/java.base/share/classes/java/lang/invoke/MemberName.java

Print this page
@@ -23,10 +23,11 @@
   * questions.
   */
  
  package java.lang.invoke;
  
+ import jdk.internal.value.PrimitiveClass;
  import sun.invoke.util.VerifyAccess;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Field;
  import java.lang.reflect.Member;

@@ -94,11 +95,12 @@
      }
  
      /** Return the simple name of this member.
       *  For a type, it is the same as {@link Class#getSimpleName}.
       *  For a method or field, it is the simple name of the member.
-      *  For a constructor, it is always {@code "<init>"}.
+      *  For an identity object constructor, it is {@code "<init>"}.
+      *  For a value class static factory method, it is {@code "<vnew>"}.
       */
      public String getName() {
          if (name == null) {
              expandFromVM();
              if (name == null) {

@@ -184,14 +186,15 @@
       *  For non-static methods or constructors, this is the type with a leading parameter,
       *  a reference to declaring class.  For static methods, it is the same as the declared type.
       */
      public MethodType getInvocationType() {
          MethodType itype = getMethodOrFieldType();
-         if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
-             return itype.changeReturnType(clazz);
+         Class<?> c = PrimitiveClass.isPrimitiveClass(clazz) ? PrimitiveClass.asValueType(clazz) : clazz;
+         if (isObjectConstructor() && getReferenceKind() == REF_newInvokeSpecial)
+             return itype.changeReturnType(c);
          if (!isStatic())
-             return itype.insertParameterTypes(0, clazz);
+             return itype.insertParameterTypes(0, c);
          return itype;
      }
  
      /** Return the declared type of this member, which
       *  must be a field or type.

@@ -250,11 +253,11 @@
          byte refKind = getReferenceKind();
          if (refKind == REF_NONE)  return isType();
          if (isField()) {
              assert(staticIsConsistent());
              assert(MethodHandleNatives.refKindIsField(refKind));
-         } else if (isConstructor()) {
+         } else if (isObjectConstructor()) {
              assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
          } else if (isMethod()) {
              assert(staticIsConsistent());
              assert(MethodHandleNatives.refKindIsMethod(refKind));
              if (clazz.isInterface())

@@ -390,10 +393,12 @@
      public boolean isProtected() {
          return Modifier.isProtected(flags);
      }
      /** Utility method to query the modifier flags of this member. */
      public boolean isFinal() {
+         // all fields declared in a value type are effectively final
+         assert(!clazz.isValue() || !isField() || Modifier.isFinal(flags));
          return Modifier.isFinal(flags);
      }
      /** Utility method to query whether this member or its defining class is final. */
      public boolean canBeStaticallyBound() {
          return Modifier.isFinal(flags | clazz.getModifiers());

@@ -411,15 +416,16 @@
          return Modifier.isNative(flags);
      }
      // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
  
      // unofficial modifier flags, used by HotSpot:
-     static final int BRIDGE    = 0x00000040;
-     static final int VARARGS   = 0x00000080;
-     static final int SYNTHETIC = 0x00001000;
-     static final int ANNOTATION= 0x00002000;
-     static final int ENUM      = 0x00004000;
+     static final int BRIDGE      = 0x00000040;
+     static final int VARARGS     = 0x00000080;
+     static final int SYNTHETIC   = 0x00001000;
+     static final int ANNOTATION  = 0x00002000;
+     static final int ENUM        = 0x00004000;
+ 
      /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
      public boolean isBridge() {
          return allFlagsSet(IS_METHOD | BRIDGE);
      }
      /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */

@@ -429,40 +435,58 @@
      /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
      public boolean isSynthetic() {
          return allFlagsSet(SYNTHETIC);
      }
  
-     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
+     /** Query whether this member is a flattened field */
+     public boolean isFlattened() { return (flags & MN_FLATTENED) == MN_FLATTENED; }
+ 
+     /** Query whether this member is a field of a primitive class. */
+     public boolean isInlineableField()  {
+         if (isField()) {
+             Class<?> type = getFieldType();
+             return PrimitiveClass.isPrimitiveValueType(type) || (type.isValue() && !PrimitiveClass.isPrimitiveClass(type));
+         }
+         return false;
+     }
+ 
+     static final String CONSTRUCTOR_NAME = "<init>";
+     static final String VALUE_FACTORY_NAME = "<vnew>";  // the ever-popular
  
      // modifiers exported by the JVM:
      static final int RECOGNIZED_MODIFIERS = 0xFFFF;
  
      // private flags, not part of RECOGNIZED_MODIFIERS:
      static final int
-             IS_METHOD        = MN_IS_METHOD,        // method (not constructor)
-             IS_CONSTRUCTOR   = MN_IS_CONSTRUCTOR,   // constructor
-             IS_FIELD         = MN_IS_FIELD,         // field
-             IS_TYPE          = MN_IS_TYPE,          // nested type
-             CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected
-             TRUSTED_FINAL    = MN_TRUSTED_FINAL;    // trusted final field
+             IS_METHOD             = MN_IS_METHOD,              // method (not object constructor)
+             IS_OBJECT_CONSTRUCTOR = MN_IS_OBJECT_CONSTRUCTOR,  // object constructor
+             IS_FIELD              = MN_IS_FIELD,               // field
+             IS_TYPE               = MN_IS_TYPE,                // nested type
+             CALLER_SENSITIVE      = MN_CALLER_SENSITIVE,       // @CallerSensitive annotation detected
+             TRUSTED_FINAL         = MN_TRUSTED_FINAL;    // trusted final field
  
      static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
-     static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
-     static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
+     static final int ALL_KINDS = IS_METHOD | IS_OBJECT_CONSTRUCTOR | IS_FIELD | IS_TYPE;
+     static final int IS_INVOCABLE = IS_METHOD | IS_OBJECT_CONSTRUCTOR;
  
      /** Utility method to query whether this member is a method or constructor. */
      public boolean isInvocable() {
          return anyFlagSet(IS_INVOCABLE);
      }
      /** Query whether this member is a method. */
      public boolean isMethod() {
          return allFlagsSet(IS_METHOD);
      }
      /** Query whether this member is a constructor. */
-     public boolean isConstructor() {
-         return allFlagsSet(IS_CONSTRUCTOR);
+     public boolean isObjectConstructor() {
+         return allFlagsSet(IS_OBJECT_CONSTRUCTOR);
+     }
+     /** Query whether this member is an object constructor or static <init> factory */
+     public boolean isStaticValueFactoryMethod() {
+         return VALUE_FACTORY_NAME.equals(name) && isMethod();
      }
+ 
      /** Query whether this member is a field. */
      public boolean isField() {
          return allFlagsSet(IS_FIELD);
      }
      /** Query whether this member is a type. */

@@ -582,11 +606,11 @@
          throw new IllegalArgumentException(this.toString());
      }
      /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
       *  In that case it must already be REF_invokeSpecial.
       */
-     public MemberName asConstructor() {
+     public MemberName asObjectConstructor() {
          switch (getReferenceKind()) {
          case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
          case REF_newInvokeSpecial:  return this;
          }
          throw new IllegalArgumentException(this.toString());

@@ -618,13 +642,18 @@
      public MemberName(Constructor<?> ctor) {
          Objects.requireNonNull(ctor);
          // fill in vmtarget, vmindex while we have ctor in hand:
          MethodHandleNatives.init(this, ctor);
          assert(isResolved() && this.clazz != null);
-         this.name = CONSTRUCTOR_NAME;
-         if (this.type == null)
-             this.type = new Object[] { void.class, ctor.getParameterTypes() };
+         this.name = this.clazz.isValue() ? VALUE_FACTORY_NAME : CONSTRUCTOR_NAME;
+         if (this.type == null) {
+             Class<?> rtype = void.class;
+             if (isStatic()) {  // a value class static factory, not a true constructor
+                 rtype = getDeclaringClass();
+             }
+             this.type = new Object[] { rtype, ctor.getParameterTypes() };
+         }
      }
      /** Create a name for the given reflected field.  The resulting name will be in a resolved state.
       */
      public MemberName(Field fld) {
          this(fld, false);

@@ -752,17 +781,18 @@
          init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
          initResolved(false);
      }
      /** Create a method or constructor name from the given components:
       *  Declaring class, name, type, reference kind.
-      *  It will be a constructor if and only if the name is {@code "<init>"}.
+      *  It will be an object constructor if and only if the name is {@code "<init>"}.
+      *  It will be a value class instance factory method if and only if the name is {@code "<vnew>"}.
       *  The declaring class may be supplied as null if this is to be a bare name and type.
       *  The last argument is optional, a boolean which requests REF_invokeSpecial.
       *  The resulting name will in an unresolved state.
       */
      public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
-         int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
+         int initFlags = CONSTRUCTOR_NAME.equals(name) ? IS_OBJECT_CONSTRUCTOR : IS_METHOD;
          init(defClass, name, type, flagsMods(initFlags, 0, refKind));
          initResolved(false);
      }
      /** Create a method, constructor, or field name from the given components:
       *  Reference kind, declaring class, name, type.

@@ -776,11 +806,11 @@
          } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
              kindFlags = IS_METHOD;
              if (!(type instanceof MethodType))
                  throw newIllegalArgumentException("not a method type");
          } else if (refKind == REF_newInvokeSpecial) {
-             kindFlags = IS_CONSTRUCTOR;
+             kindFlags = IS_OBJECT_CONSTRUCTOR;
              if (!(type instanceof MethodType) ||
                  !CONSTRUCTOR_NAME.equals(name))
                  throw newIllegalArgumentException("not a constructor type or name");
          } else {
              throw newIllegalArgumentException("bad reference kind "+refKind);

@@ -894,11 +924,11 @@
          return new IllegalAccessException(message);
      }
      private String message() {
          if (isResolved())
              return "no access";
-         else if (isConstructor())
+         else if (isObjectConstructor())
              return "no such constructor";
          else if (isMethod())
              return "no such method";
          else
              return "no such field";

@@ -907,11 +937,11 @@
          String message = message() + ": " + this;
          ReflectiveOperationException ex;
          if (isResolved() || !(resolution instanceof NoSuchMethodError ||
                                resolution instanceof NoSuchFieldError))
              ex = new IllegalAccessException(message);
-         else if (isConstructor())
+         else if (isObjectConstructor())
              ex = new NoSuchMethodException(message);
          else if (isMethod())
              ex = new NoSuchMethodException(message);
          else
              ex = new NoSuchFieldException(message);
< prev index next >