< prev index next >

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

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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

@@ -189,14 +189,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 = clazz.asPrimaryType();
+        if (isObjectConstructor() && getReferenceKind() == REF_newInvokeSpecial)
+            return itype.changeReturnType(c);
         if (!isStatic())
-            return itype.insertParameterTypes(0, clazz);
+            return itype.insertParameterTypes(0, c);
         return itype;
     }
 
     /** Utility method producing the parameter types of the method type. */
     public Class<?>[] getParameterTypes() {

@@ -282,11 +283,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())

@@ -424,10 +425,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.isInlineClass() || !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());

@@ -445,15 +448,17 @@
         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;
+    static final int FLATTENED   = 0x00008000;
+
     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
     public boolean isBridge() {
         return testAllFlags(IS_METHOD | BRIDGE);
     }
     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */

@@ -463,26 +468,45 @@
     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
     public boolean isSynthetic() {
         return testAllFlags(SYNTHETIC);
     }
 
+    /** Query whether this member is a flattened field */
+    public boolean isFlattened() { return (flags & FLATTENED) == FLATTENED; }
+
+    /** Query whether this member is a field of an inline class. */
+    public boolean isInlineable()  {
+        if (isField()) {
+            Class<?> type = getFieldType();
+            return type.isInlineClass() && type == type.asPrimaryType();
+        }
+        return false;
+    }
+
+    public boolean isIndirect()  {
+        if (isField()) {
+            return getFieldType().isIndirectType();
+        }
+        return false;
+    }
+
     static final String CONSTRUCTOR_NAME = "<init>";  // 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
+            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
 
     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;
     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
     static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
 
     /** Utility method to query whether this member is a method or constructor. */
     public boolean isInvocable() {

@@ -495,12 +519,16 @@
     /** Query whether this member is a method. */
     public boolean isMethod() {
         return testAllFlags(IS_METHOD);
     }
     /** Query whether this member is a constructor. */
-    public boolean isConstructor() {
-        return testAllFlags(IS_CONSTRUCTOR);
+    public boolean isObjectConstructor() {
+        return testAllFlags(IS_OBJECT_CONSTRUCTOR);
+    }
+    /** Query whether this member is an object constructor or static <init> factory */
+    public boolean isObjectConstructorOrStaticInitMethod() {
+        return isObjectConstructor() || (getName().equals(CONSTRUCTOR_NAME) && testAllFlags(IS_METHOD));
     }
     /** Query whether this member is a field. */
     public boolean isField() {
         return testAllFlags(IS_FIELD);
     }

@@ -625,11 +653,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());

@@ -666,12 +694,18 @@
         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() };
+        if (this.type == null) {
+            Class<?> rtype = void.class;
+            if (isStatic()) {  // a static init factory, not a true constructor
+                rtype = getDeclaringClass();
+                // FIXME: If it's a hidden class, this sig won't work.
+            }
+            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);

@@ -808,11 +842,11 @@
      *  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 = (name != null && name.equals(CONSTRUCTOR_NAME) && type.returnType() == void.class ? 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.

@@ -826,11 +860,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);

@@ -917,14 +951,23 @@
         //buf.append("#").append(System.identityHashCode(this));
         return buf.toString();
     }
     private static String getName(Object obj) {
         if (obj instanceof Class<?>)
-            return ((Class<?>)obj).getName();
+            return toTypeName((Class<?>)obj);
         return String.valueOf(obj);
     }
 
+    /*
+     * Returns the class name appended with "?" if it is the nullable projection
+     * of an inline class.
+     */
+    private static String toTypeName(Class<?> type) {
+        return type.isInlineClass() && type.isIndirectType() ? type.getName() + "?" : type.getName();
+    }
+
+
     public IllegalAccessException makeAccessException(String message, Object from) {
         message = message + ": "+ toString();
         if (from != null)  {
             if (from == MethodHandles.publicLookup()) {
                 message += ", from public Lookup";

@@ -942,11 +985,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";

@@ -955,11 +998,11 @@
         String message = message() + ": "+ toString();
         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);

@@ -1133,16 +1176,16 @@
         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
                 String name, MethodType type, Class<?> lookupClass) {
             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
             return getMembers(defc, name, type, matchFlags, lookupClass);
         }
-        /** Return a list of all constructors defined by the given class.
+        /** Return a list of all object constructors defined by the given class.
          *  Access checking is performed on behalf of the given {@code lookupClass}.
          *  Inaccessible members are not added to the last.
          */
-        public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
-            return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
+        public List<MemberName> getObjectConstructors(Class<?> defc, Class<?> lookupClass) {
+            return getMembers(defc, null, null, IS_OBJECT_CONSTRUCTOR, lookupClass);
         }
         /** Return a list of all fields defined by the given class.
          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
          *  Access checking is performed on behalf of the given {@code lookupClass}.
          *  Inaccessible members are not added to the last.
< prev index next >