1 /*
   2  * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import sun.invoke.util.BytecodeDescriptor;
  29 import sun.invoke.util.VerifyAccess;
  30 
  31 import java.lang.reflect.Constructor;
  32 import java.lang.reflect.Field;
  33 import java.lang.reflect.Method;
  34 import java.lang.reflect.Member;
  35 import java.lang.reflect.Modifier;
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.Collections;
  39 import java.util.Iterator;
  40 import java.util.List;
  41 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  42 import static java.lang.invoke.MethodHandleStatics.*;
  43 import java.util.Objects;
  44 
  45 /**
  46  * A {@code MemberName} is a compact symbolic datum which fully characterizes
  47  * a method or field reference.
  48  * A member name refers to a field, method, constructor, or member type.
  49  * Every member name has a simple name (a string) and a type (either a Class or MethodType).
  50  * A member name may also have a non-null declaring class, or it may be simply
  51  * a naked name/type pair.
  52  * A member name may also have non-zero modifier flags.
  53  * Finally, a member name may be either resolved or unresolved.
  54  * If it is resolved, the existence of the named
  55  * <p>
  56  * Whether resolved or not, a member name provides no access rights or
  57  * invocation capability to its possessor.  It is merely a compact
  58  * representation of all symbolic information necessary to link to
  59  * and properly use the named member.
  60  * <p>
  61  * When resolved, a member name's internal implementation may include references to JVM metadata.
  62  * This representation is stateless and only decriptive.
  63  * It provides no private information and no capability to use the member.
  64  * <p>
  65  * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
  66  * about the internals of a method (except its bytecodes) and also
  67  * allows invocation.  A MemberName is much lighter than a Method,
  68  * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
  69  * and those seven fields omit much of the information in Method.
  70  * @author jrose
  71  */
  72 /*non-public*/ final class MemberName implements Member, Cloneable {
  73     private Class<?>   clazz;       // class in which the method is defined
  74     private String     name;        // may be null if not yet materialized
  75     private Object     type;        // may be null if not yet materialized
  76     private int        flags;       // modifier bits; see reflect.Modifier
  77     //@Injected JVM_Method* vmtarget;
  78     //@Injected int         vmindex;
  79     private Object     resolution;  // if null, this guy is resolved
  80 
  81     /** Return the declaring class of this member.
  82      *  In the case of a bare name and type, the declaring class will be null.
  83      */
  84     public Class<?> getDeclaringClass() {
  85         return clazz;
  86     }
  87 
  88     /** Utility method producing the class loader of the declaring class. */
  89     public ClassLoader getClassLoader() {
  90         return clazz.getClassLoader();
  91     }
  92 
  93     /** Return the simple name of this member.
  94      *  For a type, it is the same as {@link Class#getSimpleName}.
  95      *  For a method or field, it is the simple name of the member.
  96      *  For a constructor, it is always {@code "&lt;init&gt;"}.
  97      */
  98     public String getName() {
  99         if (name == null) {
 100             expandFromVM();
 101             if (name == null)  return null;
 102         }
 103         return name;
 104     }
 105 
 106     public MethodType getMethodOrFieldType() {
 107         if (isInvocable())
 108             return getMethodType();
 109         if (isGetter())
 110             return MethodType.methodType(getFieldType());
 111         if (isSetter())
 112             return MethodType.methodType(void.class, getFieldType());
 113         throw new InternalError("not a method or field: "+this);
 114     }
 115 
 116     /** Return the declared type of this member, which
 117      *  must be a method or constructor.
 118      */
 119     public MethodType getMethodType() {
 120         if (type == null) {
 121             expandFromVM();
 122             if (type == null)  return null;
 123         }
 124         if (!isInvocable())
 125             throw newIllegalArgumentException("not invocable, no method type");
 126         if (type instanceof MethodType) {
 127             return (MethodType) type;
 128         }
 129         if (type instanceof String) {
 130             String sig = (String) type;
 131             MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
 132             this.type = res;
 133             return res;
 134         }
 135         if (type instanceof Object[]) {
 136             Object[] typeInfo = (Object[]) type;
 137             Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
 138             Class<?> rtype = (Class<?>) typeInfo[0];
 139             MethodType res = MethodType.methodType(rtype, ptypes);
 140             this.type = res;
 141             return res;
 142         }
 143         throw new InternalError("bad method type "+type);
 144     }
 145 
 146     /** Return the actual type under which this method or constructor must be invoked.
 147      *  For non-static methods or constructors, this is the type with a leading parameter,
 148      *  a reference to declaring class.  For static methods, it is the same as the declared type.
 149      */
 150     public MethodType getInvocationType() {
 151         MethodType itype = getMethodOrFieldType();
 152         if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
 153             return itype.changeReturnType(clazz);
 154         if (!isStatic())
 155             return itype.insertParameterTypes(0, clazz);
 156         return itype;
 157     }
 158 
 159     /** Utility method producing the parameter types of the method type. */
 160     public Class<?>[] getParameterTypes() {
 161         return getMethodType().parameterArray();
 162     }
 163 
 164     /** Utility method producing the return type of the method type. */
 165     public Class<?> getReturnType() {
 166         return getMethodType().returnType();
 167     }
 168 
 169     /** Return the declared type of this member, which
 170      *  must be a field or type.
 171      *  If it is a type member, that type itself is returned.
 172      */
 173     public Class<?> getFieldType() {
 174         if (type == null) {
 175             expandFromVM();
 176             if (type == null)  return null;
 177         }
 178         if (isInvocable())
 179             throw newIllegalArgumentException("not a field or nested class, no simple type");
 180         if (type instanceof Class<?>) {
 181             return (Class<?>) type;
 182         }
 183         if (type instanceof String) {
 184             String sig = (String) type;
 185             MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
 186             Class<?> res = mtype.returnType();
 187             this.type = res;
 188             return res;
 189         }
 190         throw new InternalError("bad field type "+type);
 191     }
 192 
 193     /** Utility method to produce either the method type or field type of this member. */
 194     public Object getType() {
 195         return (isInvocable() ? getMethodType() : getFieldType());
 196     }
 197 
 198     /** Utility method to produce the signature of this member,
 199      *  used within the class file format to describe its type.
 200      */
 201     public String getSignature() {
 202         if (type == null) {
 203             expandFromVM();
 204             if (type == null)  return null;
 205         }
 206         if (type instanceof String)
 207             return (String) type;
 208         if (isInvocable())
 209             return BytecodeDescriptor.unparse(getMethodType());
 210         else
 211             return BytecodeDescriptor.unparse(getFieldType());
 212     }
 213 
 214     /** Return the modifier flags of this member.
 215      *  @see java.lang.reflect.Modifier
 216      */
 217     public int getModifiers() {
 218         return (flags & RECOGNIZED_MODIFIERS);
 219     }
 220 
 221     /** Return the reference kind of this member, or zero if none.
 222      */
 223     public byte getReferenceKind() {
 224         return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
 225     }
 226     private boolean referenceKindIsConsistent() {
 227         byte refKind = getReferenceKind();
 228         if (refKind == REF_NONE)  return isType();
 229         if (isField()) {
 230             assert(staticIsConsistent());
 231             assert(MethodHandleNatives.refKindIsField(refKind));
 232         } else if (isConstructor()) {
 233             assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
 234         } else if (isMethod()) {
 235             assert(staticIsConsistent());
 236             assert(MethodHandleNatives.refKindIsMethod(refKind));
 237             if (clazz.isInterface())
 238                 assert(refKind == REF_invokeInterface ||
 239                        refKind == REF_invokeVirtual && isObjectPublicMethod());
 240         } else {
 241             assert(false);
 242         }
 243         return true;
 244     }
 245     private boolean isObjectPublicMethod() {
 246         if (clazz == Object.class)  return true;
 247         MethodType mtype = getMethodType();
 248         if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
 249             return true;
 250         if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
 251             return true;
 252         if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
 253             return true;
 254         return false;
 255     }
 256     /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) {
 257         int refKind = getReferenceKind();
 258         if (refKind == originalRefKind)  return true;
 259         switch (originalRefKind) {
 260         case REF_invokeInterface:
 261             // Looking up an interface method, can get (e.g.) Object.hashCode
 262             assert(refKind == REF_invokeVirtual ||
 263                    refKind == REF_invokeSpecial) : this;
 264             return true;
 265         case REF_invokeVirtual:
 266         case REF_newInvokeSpecial:
 267             // Looked up a virtual, can get (e.g.) final String.hashCode.
 268             assert(refKind == REF_invokeSpecial) : this;
 269             return true;
 270         }
 271         assert(false) : this;
 272         return true;
 273     }
 274     private boolean staticIsConsistent() {
 275         byte refKind = getReferenceKind();
 276         return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
 277     }
 278     private boolean vminfoIsConsistent() {
 279         byte refKind = getReferenceKind();
 280         assert(isResolved());  // else don't call
 281         Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
 282         assert(vminfo instanceof Object[]);
 283         long vmindex = (Long) ((Object[])vminfo)[0];
 284         Object vmtarget = ((Object[])vminfo)[1];
 285         if (MethodHandleNatives.refKindIsField(refKind)) {
 286             assert(vmindex >= 0) : vmindex + ":" + this;
 287             assert(vmtarget instanceof Class);
 288         } else {
 289             if (MethodHandleNatives.refKindDoesDispatch(refKind))
 290                 assert(vmindex >= 0) : vmindex + ":" + this;
 291             else
 292                 assert(vmindex < 0) : vmindex;
 293             assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
 294         }
 295         return true;
 296     }
 297 
 298     private MemberName changeReferenceKind(byte refKind, byte oldKind) {
 299         assert(getReferenceKind() == oldKind);
 300         assert(MethodHandleNatives.refKindIsValid(refKind));
 301         flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
 302 //        if (isConstructor() && refKind != REF_newInvokeSpecial)
 303 //            flags += (IS_METHOD - IS_CONSTRUCTOR);
 304 //        else if (refKind == REF_newInvokeSpecial && isMethod())
 305 //            flags += (IS_CONSTRUCTOR - IS_METHOD);
 306         return this;
 307     }
 308 
 309     private boolean testFlags(int mask, int value) {
 310         return (flags & mask) == value;
 311     }
 312     private boolean testAllFlags(int mask) {
 313         return testFlags(mask, mask);
 314     }
 315     private boolean testAnyFlags(int mask) {
 316         return !testFlags(mask, 0);
 317     }
 318 
 319     /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
 320     public boolean isMethodHandleInvoke() {
 321         final int bits = Modifier.NATIVE | Modifier.FINAL;
 322         final int negs = Modifier.STATIC;
 323         if (testFlags(bits | negs, bits) &&
 324             clazz == MethodHandle.class) {
 325             return name.equals("invoke") || name.equals("invokeExact");
 326         }
 327         return false;
 328     }
 329 
 330     /** Utility method to query the modifier flags of this member. */
 331     public boolean isStatic() {
 332         return Modifier.isStatic(flags);
 333     }
 334     /** Utility method to query the modifier flags of this member. */
 335     public boolean isPublic() {
 336         return Modifier.isPublic(flags);
 337     }
 338     /** Utility method to query the modifier flags of this member. */
 339     public boolean isPrivate() {
 340         return Modifier.isPrivate(flags);
 341     }
 342     /** Utility method to query the modifier flags of this member. */
 343     public boolean isProtected() {
 344         return Modifier.isProtected(flags);
 345     }
 346     /** Utility method to query the modifier flags of this member. */
 347     public boolean isFinal() {
 348         return Modifier.isFinal(flags);
 349     }
 350     /** Utility method to query whether this member or its defining class is final. */
 351     public boolean canBeStaticallyBound() {
 352         return Modifier.isFinal(flags | clazz.getModifiers());
 353     }
 354     /** Utility method to query the modifier flags of this member. */
 355     public boolean isVolatile() {
 356         return Modifier.isVolatile(flags);
 357     }
 358     /** Utility method to query the modifier flags of this member. */
 359     public boolean isAbstract() {
 360         return Modifier.isAbstract(flags);
 361     }
 362     /** Utility method to query the modifier flags of this member. */
 363     public boolean isNative() {
 364         return Modifier.isNative(flags);
 365     }
 366     // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
 367 
 368     // unofficial modifier flags, used by HotSpot:
 369     static final int BRIDGE    = 0x00000040;
 370     static final int VARARGS   = 0x00000080;
 371     static final int SYNTHETIC = 0x00001000;
 372     static final int ANNOTATION= 0x00002000;
 373     static final int ENUM      = 0x00004000;
 374     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 375     public boolean isBridge() {
 376         return testAllFlags(IS_METHOD | BRIDGE);
 377     }
 378     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 379     public boolean isVarargs() {
 380         return testAllFlags(VARARGS) && isInvocable();
 381     }
 382     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 383     public boolean isSynthetic() {
 384         return testAllFlags(SYNTHETIC);
 385     }
 386 
 387     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
 388 
 389     // modifiers exported by the JVM:
 390     static final int RECOGNIZED_MODIFIERS = 0xFFFF;
 391 
 392     // private flags, not part of RECOGNIZED_MODIFIERS:
 393     static final int
 394             IS_METHOD        = MN_IS_METHOD,        // method (not constructor)
 395             IS_CONSTRUCTOR   = MN_IS_CONSTRUCTOR,   // constructor
 396             IS_FIELD         = MN_IS_FIELD,         // field
 397             IS_TYPE          = MN_IS_TYPE,          // nested type
 398             CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
 399 
 400     static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
 401     static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
 402     static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
 403     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
 404     static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
 405 
 406     /** Utility method to query whether this member is a method or constructor. */
 407     public boolean isInvocable() {
 408         return testAnyFlags(IS_INVOCABLE);
 409     }
 410     /** Utility method to query whether this member is a method, constructor, or field. */
 411     public boolean isFieldOrMethod() {
 412         return testAnyFlags(IS_FIELD_OR_METHOD);
 413     }
 414     /** Query whether this member is a method. */
 415     public boolean isMethod() {
 416         return testAllFlags(IS_METHOD);
 417     }
 418     /** Query whether this member is a constructor. */
 419     public boolean isConstructor() {
 420         return testAllFlags(IS_CONSTRUCTOR);
 421     }
 422     /** Query whether this member is a field. */
 423     public boolean isField() {
 424         return testAllFlags(IS_FIELD);
 425     }
 426     /** Query whether this member is a type. */
 427     public boolean isType() {
 428         return testAllFlags(IS_TYPE);
 429     }
 430     /** Utility method to query whether this member is neither public, private, nor protected. */
 431     public boolean isPackage() {
 432         return !testAnyFlags(ALL_ACCESS);
 433     }
 434     /** Query whether this member has a CallerSensitive annotation. */
 435     public boolean isCallerSensitive() {
 436         return testAllFlags(CALLER_SENSITIVE);
 437     }
 438 
 439     /** Utility method to query whether this member is accessible from a given lookup class. */
 440     public boolean isAccessibleFrom(Class<?> lookupClass) {
 441         return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
 442                                                lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
 443     }
 444 
 445     /** Initialize a query.   It is not resolved. */
 446     private void init(Class<?> defClass, String name, Object type, int flags) {
 447         // defining class is allowed to be null (for a naked name/type pair)
 448         //name.toString();  // null check
 449         //type.equals(type);  // null check
 450         // fill in fields:
 451         this.clazz = defClass;
 452         this.name = name;
 453         this.type = type;
 454         this.flags = flags;
 455         assert(testAnyFlags(ALL_KINDS));
 456         assert(this.resolution == null);  // nobody should have touched this yet
 457         //assert(referenceKindIsConsistent());  // do this after resolution
 458     }
 459 
 460     private void expandFromVM() {
 461         if (!isResolved())  return;
 462         if (type instanceof Object[])
 463             type = null;  // don't saddle JVM w/ typeInfo
 464         MethodHandleNatives.expand(this);
 465     }
 466 
 467     // Capturing information from the Core Reflection API:
 468     private static int flagsMods(int flags, int mods, byte refKind) {
 469         assert((flags & RECOGNIZED_MODIFIERS) == 0);
 470         assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
 471         assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
 472         return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
 473     }
 474     /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
 475     public MemberName(Method m) {
 476         this(m, false);
 477     }
 478     @SuppressWarnings("LeakingThisInConstructor")
 479     public MemberName(Method m, boolean wantSpecial) {
 480         m.getClass();  // NPE check
 481         // fill in vmtarget, vmindex while we have m in hand:
 482         MethodHandleNatives.init(this, m);
 483         assert(isResolved() && this.clazz != null);
 484         this.name = m.getName();
 485         if (this.type == null)
 486             this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
 487         if (wantSpecial) {
 488             if (getReferenceKind() == REF_invokeVirtual)
 489                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 490         }
 491     }
 492     public MemberName asSpecial() {
 493         switch (getReferenceKind()) {
 494         case REF_invokeSpecial:     return this;
 495         case REF_invokeVirtual:     return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 496         case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
 497         }
 498         throw new IllegalArgumentException(this.toString());
 499     }
 500     public MemberName asConstructor() {
 501         switch (getReferenceKind()) {
 502         case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
 503         case REF_newInvokeSpecial:  return this;
 504         }
 505         throw new IllegalArgumentException(this.toString());
 506     }
 507     /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
 508     @SuppressWarnings("LeakingThisInConstructor")
 509     public MemberName(Constructor<?> ctor) {
 510         ctor.getClass();  // NPE check
 511         // fill in vmtarget, vmindex while we have ctor in hand:
 512         MethodHandleNatives.init(this, ctor);
 513         assert(isResolved() && this.clazz != null);
 514         this.name = CONSTRUCTOR_NAME;
 515         if (this.type == null)
 516             this.type = new Object[] { void.class, ctor.getParameterTypes() };
 517     }
 518     /** Create a name for the given reflected field.  The resulting name will be in a resolved state.
 519      */
 520     public MemberName(Field fld) {
 521         this(fld, false);
 522     }
 523     @SuppressWarnings("LeakingThisInConstructor")
 524     public MemberName(Field fld, boolean makeSetter) {
 525         fld.getClass();  // NPE check
 526         // fill in vmtarget, vmindex while we have fld in hand:
 527         MethodHandleNatives.init(this, fld);
 528         assert(isResolved() && this.clazz != null);
 529         this.name = fld.getName();
 530         this.type = fld.getType();
 531         assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
 532         byte refKind = this.getReferenceKind();
 533         assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
 534         if (makeSetter) {
 535             changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
 536         }
 537     }
 538     public boolean isGetter() {
 539         return MethodHandleNatives.refKindIsGetter(getReferenceKind());
 540     }
 541     public boolean isSetter() {
 542         return MethodHandleNatives.refKindIsSetter(getReferenceKind());
 543     }
 544     public MemberName asSetter() {
 545         byte refKind = getReferenceKind();
 546         assert(MethodHandleNatives.refKindIsGetter(refKind));
 547         assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
 548         byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
 549         return clone().changeReferenceKind(setterRefKind, refKind);
 550     }
 551     /** Create a name for the given class.  The resulting name will be in a resolved state. */
 552     public MemberName(Class<?> type) {
 553         init(type.getDeclaringClass(), type.getSimpleName(), type,
 554                 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
 555         initResolved(true);
 556     }
 557 
 558     // bare-bones constructor; the JVM will fill it in
 559     MemberName() { }
 560 
 561     // locally useful cloner
 562     @Override protected MemberName clone() {
 563         try {
 564             return (MemberName) super.clone();
 565         } catch (CloneNotSupportedException ex) {
 566             throw newInternalError(ex);
 567         }
 568      }
 569 
 570     /** Get the definition of this member name.
 571      *  This may be in a super-class of the declaring class of this member.
 572      */
 573     public MemberName getDefinition() {
 574         if (!isResolved())  throw new IllegalStateException("must be resolved: "+this);
 575         if (isType())  return this;
 576         MemberName res = this.clone();
 577         res.clazz = null;
 578         res.type = null;
 579         res.name = null;
 580         res.resolution = res;
 581         res.expandFromVM();
 582         assert(res.getName().equals(this.getName()));
 583         return res;
 584     }
 585 
 586     @Override
 587     public int hashCode() {
 588         return Objects.hash(clazz, flags, name, getType());
 589     }
 590     @Override
 591     public boolean equals(Object that) {
 592         return (that instanceof MemberName && this.equals((MemberName)that));
 593     }
 594 
 595     /** Decide if two member names have exactly the same symbolic content.
 596      *  Does not take into account any actual class members, so even if
 597      *  two member names resolve to the same actual member, they may
 598      *  be distinct references.
 599      */
 600     public boolean equals(MemberName that) {
 601         if (this == that)  return true;
 602         if (that == null)  return false;
 603         return this.clazz == that.clazz
 604                 && this.flags == that.flags
 605                 && Objects.equals(this.name, that.name)
 606                 && Objects.equals(this.getType(), that.getType());
 607     }
 608 
 609     // Construction from symbolic parts, for queries:
 610     /** Create a field or type name from the given components:  Declaring class, name, type, reference kind.
 611      *  The declaring class may be supplied as null if this is to be a bare name and type.
 612      *  The resulting name will in an unresolved state.
 613      */
 614     public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
 615         init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
 616         initResolved(false);
 617     }
 618     /** Create a field or type name from the given components:  Declaring class, name, type.
 619      *  The declaring class may be supplied as null if this is to be a bare name and type.
 620      *  The modifier flags default to zero.
 621      *  The resulting name will in an unresolved state.
 622      */
 623     public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
 624         this(defClass, name, type, REF_NONE);
 625         initResolved(false);
 626     }
 627     /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
 628      *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
 629      *  The declaring class may be supplied as null if this is to be a bare name and type.
 630      *  The last argument is optional, a boolean which requests REF_invokeSpecial.
 631      *  The resulting name will in an unresolved state.
 632      */
 633     public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
 634         @SuppressWarnings("LocalVariableHidesMemberVariable")
 635         int flags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
 636         init(defClass, name, type, flagsMods(flags, 0, refKind));
 637         initResolved(false);
 638     }
 639 //    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
 640 //     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
 641 //     *  The declaring class may be supplied as null if this is to be a bare name and type.
 642 //     *  The modifier flags default to zero.
 643 //     *  The resulting name will in an unresolved state.
 644 //     */
 645 //    public MemberName(Class<?> defClass, String name, MethodType type, Void unused) {
 646 //        this(defClass, name, type, REF_NONE);
 647 //    }
 648 
 649     /** Query whether this member name is resolved to a non-static, non-final method.
 650      */
 651     public boolean hasReceiverTypeDispatch() {
 652         return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
 653     }
 654 
 655     /** Query whether this member name is resolved.
 656      *  A resolved member name is one for which the JVM has found
 657      *  a method, constructor, field, or type binding corresponding exactly to the name.
 658      *  (Document?)
 659      */
 660     public boolean isResolved() {
 661         return resolution == null;
 662     }
 663 
 664     private void initResolved(boolean isResolved) {
 665         assert(this.resolution == null);  // not initialized yet!
 666         if (!isResolved)
 667             this.resolution = this;
 668         assert(isResolved() == isResolved);
 669     }
 670 
 671     void checkForTypeAlias() {
 672         if (isInvocable()) {
 673             MethodType type;
 674             if (this.type instanceof MethodType)
 675                 type = (MethodType) this.type;
 676             else
 677                 this.type = type = getMethodType();
 678             if (type.erase() == type)  return;
 679             if (VerifyAccess.isTypeVisible(type, clazz))  return;
 680             throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
 681         } else {
 682             Class<?> type;
 683             if (this.type instanceof Class<?>)
 684                 type = (Class<?>) this.type;
 685             else
 686                 this.type = type = getFieldType();
 687             if (VerifyAccess.isTypeVisible(type, clazz))  return;
 688             throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
 689         }
 690     }
 691 
 692 
 693     /** Produce a string form of this member name.
 694      *  For types, it is simply the type's own string (as reported by {@code toString}).
 695      *  For fields, it is {@code "DeclaringClass.name/type"}.
 696      *  For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
 697      *  If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
 698      *  If the member is unresolved, a prefix {@code "*."} is prepended.
 699      */
 700     @SuppressWarnings("LocalVariableHidesMemberVariable")
 701     @Override
 702     public String toString() {
 703         if (isType())
 704             return type.toString();  // class java.lang.String
 705         // else it is a field, method, or constructor
 706         StringBuilder buf = new StringBuilder();
 707         if (getDeclaringClass() != null) {
 708             buf.append(getName(clazz));
 709             buf.append('.');
 710         }
 711         String name = getName();
 712         buf.append(name == null ? "*" : name);
 713         Object type = getType();
 714         if (!isInvocable()) {
 715             buf.append('/');
 716             buf.append(type == null ? "*" : getName(type));
 717         } else {
 718             buf.append(type == null ? "(*)*" : getName(type));
 719         }
 720         byte refKind = getReferenceKind();
 721         if (refKind != REF_NONE) {
 722             buf.append('/');
 723             buf.append(MethodHandleNatives.refKindName(refKind));
 724         }
 725         //buf.append("#").append(System.identityHashCode(this));
 726         return buf.toString();
 727     }
 728     private static String getName(Object obj) {
 729         if (obj instanceof Class<?>)
 730             return ((Class<?>)obj).getName();
 731         return String.valueOf(obj);
 732     }
 733 
 734     public IllegalAccessException makeAccessException(String message, Object from) {
 735         message = message + ": "+ toString();
 736         if (from != null)  message += ", from " + from;
 737         return new IllegalAccessException(message);
 738     }
 739     private String message() {
 740         if (isResolved())
 741             return "no access";
 742         else if (isConstructor())
 743             return "no such constructor";
 744         else if (isMethod())
 745             return "no such method";
 746         else
 747             return "no such field";
 748     }
 749     public ReflectiveOperationException makeAccessException() {
 750         String message = message() + ": "+ toString();
 751         ReflectiveOperationException ex;
 752         if (isResolved() || !(resolution instanceof NoSuchMethodError ||
 753                               resolution instanceof NoSuchFieldError))
 754             ex = new IllegalAccessException(message);
 755         else if (isConstructor())
 756             ex = new NoSuchMethodException(message);
 757         else if (isMethod())
 758             ex = new NoSuchMethodException(message);
 759         else
 760             ex = new NoSuchFieldException(message);
 761         if (resolution instanceof Throwable)
 762             ex.initCause((Throwable) resolution);
 763         return ex;
 764     }
 765 
 766     /** Actually making a query requires an access check. */
 767     /*non-public*/ static Factory getFactory() {
 768         return Factory.INSTANCE;
 769     }
 770     /** A factory type for resolving member names with the help of the VM.
 771      *  TBD: Define access-safe public constructors for this factory.
 772      */
 773     /*non-public*/ static class Factory {
 774         private Factory() { } // singleton pattern
 775         static Factory INSTANCE = new Factory();
 776 
 777         private static int ALLOWED_FLAGS = ALL_KINDS;
 778 
 779         /// Queries
 780         List<MemberName> getMembers(Class<?> defc,
 781                 String matchName, Object matchType,
 782                 int matchFlags, Class<?> lookupClass) {
 783             matchFlags &= ALLOWED_FLAGS;
 784             String matchSig = null;
 785             if (matchType != null) {
 786                 matchSig = BytecodeDescriptor.unparse(matchType);
 787                 if (matchSig.startsWith("("))
 788                     matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
 789                 else
 790                     matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
 791             }
 792             final int BUF_MAX = 0x2000;
 793             int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
 794             MemberName[] buf = newMemberBuffer(len1);
 795             int totalCount = 0;
 796             ArrayList<MemberName[]> bufs = null;
 797             int bufCount = 0;
 798             for (;;) {
 799                 bufCount = MethodHandleNatives.getMembers(defc,
 800                         matchName, matchSig, matchFlags,
 801                         lookupClass,
 802                         totalCount, buf);
 803                 if (bufCount <= buf.length) {
 804                     if (bufCount < 0)  bufCount = 0;
 805                     totalCount += bufCount;
 806                     break;
 807                 }
 808                 // JVM returned to us with an intentional overflow!
 809                 totalCount += buf.length;
 810                 int excess = bufCount - buf.length;
 811                 if (bufs == null)  bufs = new ArrayList<>(1);
 812                 bufs.add(buf);
 813                 int len2 = buf.length;
 814                 len2 = Math.max(len2, excess);
 815                 len2 = Math.max(len2, totalCount / 4);
 816                 buf = newMemberBuffer(Math.min(BUF_MAX, len2));
 817             }
 818             ArrayList<MemberName> result = new ArrayList<>(totalCount);
 819             if (bufs != null) {
 820                 for (MemberName[] buf0 : bufs) {
 821                     Collections.addAll(result, buf0);
 822                 }
 823             }
 824             result.addAll(Arrays.asList(buf).subList(0, bufCount));
 825             // Signature matching is not the same as type matching, since
 826             // one signature might correspond to several types.
 827             // So if matchType is a Class or MethodType, refilter the results.
 828             if (matchType != null && matchType != matchSig) {
 829                 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
 830                     MemberName m = it.next();
 831                     if (!matchType.equals(m.getType()))
 832                         it.remove();
 833                 }
 834             }
 835             return result;
 836         }
 837         /** Produce a resolved version of the given member.
 838          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 839          *  Access checking is performed on behalf of the given {@code lookupClass}.
 840          *  If lookup fails or access is not permitted, null is returned.
 841          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
 842          */
 843         private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
 844             MemberName m = ref.clone();  // JVM will side-effect the ref
 845             assert(refKind == m.getReferenceKind());
 846             try {
 847                 m = MethodHandleNatives.resolve(m, lookupClass);
 848                 m.checkForTypeAlias();
 849                 m.resolution = null;
 850             } catch (LinkageError ex) {
 851                 // JVM reports that the "bytecode behavior" would get an error
 852                 assert(!m.isResolved());
 853                 m.resolution = ex;
 854                 return m;
 855             }
 856             assert(m.referenceKindIsConsistent());
 857             m.initResolved(true);
 858             assert(m.vminfoIsConsistent());
 859             return m;
 860         }
 861         /** Produce a resolved version of the given member.
 862          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 863          *  Access checking is performed on behalf of the given {@code lookupClass}.
 864          *  If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
 865          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
 866          */
 867         public
 868         <NoSuchMemberException extends ReflectiveOperationException>
 869         MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
 870                                  Class<NoSuchMemberException> nsmClass)
 871                 throws IllegalAccessException, NoSuchMemberException {
 872             MemberName result = resolve(refKind, m, lookupClass);
 873             if (result.isResolved())
 874                 return result;
 875             ReflectiveOperationException ex = result.makeAccessException();
 876             if (ex instanceof IllegalAccessException)  throw (IllegalAccessException) ex;
 877             throw nsmClass.cast(ex);
 878         }
 879         /** Produce a resolved version of the given member.
 880          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 881          *  Access checking is performed on behalf of the given {@code lookupClass}.
 882          *  If lookup fails or access is not permitted, return null.
 883          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
 884          */
 885         public
 886         MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
 887             MemberName result = resolve(refKind, m, lookupClass);
 888             if (result.isResolved())
 889                 return result;
 890             return null;
 891         }
 892         /** Return a list of all methods defined by the given class.
 893          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 894          *  Access checking is performed on behalf of the given {@code lookupClass}.
 895          *  Inaccessible members are not added to the last.
 896          */
 897         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
 898                 Class<?> lookupClass) {
 899             return getMethods(defc, searchSupers, null, null, lookupClass);
 900         }
 901         /** Return a list of matching methods defined by the given class.
 902          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 903          *  Returned methods will match the name (if not null) and the type (if not null).
 904          *  Access checking is performed on behalf of the given {@code lookupClass}.
 905          *  Inaccessible members are not added to the last.
 906          */
 907         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
 908                 String name, MethodType type, Class<?> lookupClass) {
 909             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 910             return getMembers(defc, name, type, matchFlags, lookupClass);
 911         }
 912         /** Return a list of all constructors defined by the given class.
 913          *  Access checking is performed on behalf of the given {@code lookupClass}.
 914          *  Inaccessible members are not added to the last.
 915          */
 916         public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
 917             return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
 918         }
 919         /** Return a list of all fields defined by the given class.
 920          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 921          *  Access checking is performed on behalf of the given {@code lookupClass}.
 922          *  Inaccessible members are not added to the last.
 923          */
 924         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
 925                 Class<?> lookupClass) {
 926             return getFields(defc, searchSupers, null, null, lookupClass);
 927         }
 928         /** Return a list of all fields defined by the given class.
 929          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 930          *  Returned fields will match the name (if not null) and the type (if not null).
 931          *  Access checking is performed on behalf of the given {@code lookupClass}.
 932          *  Inaccessible members are not added to the last.
 933          */
 934         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
 935                 String name, Class<?> type, Class<?> lookupClass) {
 936             int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 937             return getMembers(defc, name, type, matchFlags, lookupClass);
 938         }
 939         /** Return a list of all nested types defined by the given class.
 940          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 941          *  Access checking is performed on behalf of the given {@code lookupClass}.
 942          *  Inaccessible members are not added to the last.
 943          */
 944         public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
 945                 Class<?> lookupClass) {
 946             int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 947             return getMembers(defc, null, null, matchFlags, lookupClass);
 948         }
 949         private static MemberName[] newMemberBuffer(int length) {
 950             MemberName[] buf = new MemberName[length];
 951             // fill the buffer with dummy structs for the JVM to fill in
 952             for (int i = 0; i < length; i++)
 953                 buf[i] = new MemberName();
 954             return buf;
 955         }
 956     }
 957 
 958 //    static {
 959 //        System.out.println("Hello world!  My methods are:");
 960 //        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
 961 //    }
 962 }