< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 2008, 2017, 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


 174         }
 175         if (!isInvocable()) {
 176             throw newIllegalArgumentException("not invocable, no method type");
 177         }
 178 
 179         // Get a snapshot of type which doesn't get changed by racing threads.
 180         final Object type = this.type;
 181         if (type instanceof String) {
 182             return (String) type;
 183         } else {
 184             return getMethodType().toMethodDescriptorString();
 185         }
 186     }
 187 
 188     /** Return the actual type under which this method or constructor must be invoked.
 189      *  For non-static methods or constructors, this is the type with a leading parameter,
 190      *  a reference to declaring class.  For static methods, it is the same as the declared type.
 191      */
 192     public MethodType getInvocationType() {
 193         MethodType itype = getMethodOrFieldType();
 194         if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
 195             return itype.changeReturnType(clazz);

 196         if (!isStatic())
 197             return itype.insertParameterTypes(0, clazz);
 198         return itype;
 199     }
 200 
 201     /** Utility method producing the parameter types of the method type. */
 202     public Class<?>[] getParameterTypes() {
 203         return getMethodType().parameterArray();
 204     }
 205 
 206     /** Utility method producing the return type of the method type. */
 207     public Class<?> getReturnType() {
 208         return getMethodType().returnType();
 209     }
 210 
 211     /** Return the declared type of this member, which
 212      *  must be a field or type.
 213      *  If it is a type member, that type itself is returned.
 214      */
 215     public Class<?> getFieldType() {
 216         if (type == null) {
 217             expandFromVM();


 267     }
 268 
 269     /** Return the modifier flags of this member.
 270      *  @see java.lang.reflect.Modifier
 271      */
 272     public int getModifiers() {
 273         return (flags & RECOGNIZED_MODIFIERS);
 274     }
 275 
 276     /** Return the reference kind of this member, or zero if none.
 277      */
 278     public byte getReferenceKind() {
 279         return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
 280     }
 281     private boolean referenceKindIsConsistent() {
 282         byte refKind = getReferenceKind();
 283         if (refKind == REF_NONE)  return isType();
 284         if (isField()) {
 285             assert(staticIsConsistent());
 286             assert(MethodHandleNatives.refKindIsField(refKind));
 287         } else if (isConstructor()) {
 288             assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
 289         } else if (isMethod()) {
 290             assert(staticIsConsistent());
 291             assert(MethodHandleNatives.refKindIsMethod(refKind));
 292             if (clazz.isInterface())
 293                 assert(refKind == REF_invokeInterface ||
 294                        refKind == REF_invokeStatic    ||
 295                        refKind == REF_invokeSpecial   ||
 296                        refKind == REF_invokeVirtual && isObjectPublicMethod());
 297         } else {
 298             assert(false);
 299         }
 300         return true;
 301     }
 302     private boolean isObjectPublicMethod() {
 303         if (clazz == Object.class)  return true;
 304         MethodType mtype = getMethodType();
 305         if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
 306             return true;
 307         if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)


 409     private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
 410 
 411     /** Utility method to query the modifier flags of this member. */
 412     public boolean isStatic() {
 413         return Modifier.isStatic(flags);
 414     }
 415     /** Utility method to query the modifier flags of this member. */
 416     public boolean isPublic() {
 417         return Modifier.isPublic(flags);
 418     }
 419     /** Utility method to query the modifier flags of this member. */
 420     public boolean isPrivate() {
 421         return Modifier.isPrivate(flags);
 422     }
 423     /** Utility method to query the modifier flags of this member. */
 424     public boolean isProtected() {
 425         return Modifier.isProtected(flags);
 426     }
 427     /** Utility method to query the modifier flags of this member. */
 428     public boolean isFinal() {


 429         return Modifier.isFinal(flags);
 430     }
 431     /** Utility method to query whether this member or its defining class is final. */
 432     public boolean canBeStaticallyBound() {
 433         return Modifier.isFinal(flags | clazz.getModifiers());
 434     }
 435     /** Utility method to query the modifier flags of this member. */
 436     public boolean isVolatile() {
 437         return Modifier.isVolatile(flags);
 438     }
 439     /** Utility method to query the modifier flags of this member. */
 440     public boolean isAbstract() {
 441         return Modifier.isAbstract(flags);
 442     }
 443     /** Utility method to query the modifier flags of this member. */
 444     public boolean isNative() {
 445         return Modifier.isNative(flags);
 446     }
 447     // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
 448 
 449     // unofficial modifier flags, used by HotSpot:
 450     static final int BRIDGE    = 0x00000040;
 451     static final int VARARGS   = 0x00000080;
 452     static final int SYNTHETIC = 0x00001000;
 453     static final int ANNOTATION= 0x00002000;
 454     static final int ENUM      = 0x00004000;


 455     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 456     public boolean isBridge() {
 457         return testAllFlags(IS_METHOD | BRIDGE);
 458     }
 459     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 460     public boolean isVarargs() {
 461         return testAllFlags(VARARGS) && isInvocable();
 462     }
 463     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 464     public boolean isSynthetic() {
 465         return testAllFlags(SYNTHETIC);
 466     }
 467 



















 468     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
 469 
 470     // modifiers exported by the JVM:
 471     static final int RECOGNIZED_MODIFIERS = 0xFFFF;
 472 
 473     // private flags, not part of RECOGNIZED_MODIFIERS:
 474     static final int
 475             IS_METHOD        = MN_IS_METHOD,        // method (not constructor)
 476             IS_CONSTRUCTOR   = MN_IS_CONSTRUCTOR,   // constructor
 477             IS_FIELD         = MN_IS_FIELD,         // field
 478             IS_TYPE          = MN_IS_TYPE,          // nested type
 479             CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
 480 
 481     static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
 482     static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
 483     static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
 484     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
 485     static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
 486 
 487     /** Utility method to query whether this member is a method or constructor. */
 488     public boolean isInvocable() {
 489         return testAnyFlags(IS_INVOCABLE);
 490     }
 491     /** Utility method to query whether this member is a method, constructor, or field. */
 492     public boolean isFieldOrMethod() {
 493         return testAnyFlags(IS_FIELD_OR_METHOD);
 494     }
 495     /** Query whether this member is a method. */
 496     public boolean isMethod() {
 497         return testAllFlags(IS_METHOD);
 498     }
 499     /** Query whether this member is a constructor. */
 500     public boolean isConstructor() {
 501         return testAllFlags(IS_CONSTRUCTOR);




 502     }
 503     /** Query whether this member is a field. */
 504     public boolean isField() {
 505         return testAllFlags(IS_FIELD);
 506     }
 507     /** Query whether this member is a type. */
 508     public boolean isType() {
 509         return testAllFlags(IS_TYPE);
 510     }
 511     /** Utility method to query whether this member is neither public, private, nor protected. */
 512     public boolean isPackage() {
 513         return !testAnyFlags(ALL_ACCESS);
 514     }
 515     /** Query whether this member has a CallerSensitive annotation. */
 516     public boolean isCallerSensitive() {
 517         return testAllFlags(CALLER_SENSITIVE);
 518     }
 519 
 520     /** Utility method to query whether this member is accessible from a given lookup class. */
 521     public boolean isAccessibleFrom(Class<?> lookupClass) {


 610                 throw new AbstractMethodError(this.toString());
 611             if (getReferenceKind() == REF_invokeVirtual)
 612                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 613             else if (getReferenceKind() == REF_invokeInterface)
 614                 // invokeSpecial on a default method
 615                 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
 616         }
 617     }
 618     public MemberName asSpecial() {
 619         switch (getReferenceKind()) {
 620         case REF_invokeSpecial:     return this;
 621         case REF_invokeVirtual:     return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 622         case REF_invokeInterface:   return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
 623         case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
 624         }
 625         throw new IllegalArgumentException(this.toString());
 626     }
 627     /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
 628      *  In that case it must already be REF_invokeSpecial.
 629      */
 630     public MemberName asConstructor() {
 631         switch (getReferenceKind()) {
 632         case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
 633         case REF_newInvokeSpecial:  return this;
 634         }
 635         throw new IllegalArgumentException(this.toString());
 636     }
 637     /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
 638      *  REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
 639      *  The end result is to get a fully virtualized version of the MN.
 640      *  (Note that resolving in the JVM will sometimes devirtualize, changing
 641      *  REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
 642      *  in some corner cases to either of the previous two; this transform
 643      *  undoes that change under the assumption that it occurred.)
 644      */
 645     public MemberName asNormalOriginal() {
 646         byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
 647         byte refKind = getReferenceKind();
 648         byte newRefKind = refKind;
 649         MemberName result = this;
 650         switch (refKind) {
 651         case REF_invokeInterface:
 652         case REF_invokeVirtual:
 653         case REF_invokeSpecial:
 654             newRefKind = normalVirtual;
 655             break;
 656         }
 657         if (newRefKind == refKind)
 658             return this;
 659         result = clone().changeReferenceKind(newRefKind, refKind);
 660         assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
 661         return result;
 662     }
 663     /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
 664     @SuppressWarnings("LeakingThisInConstructor")
 665     public MemberName(Constructor<?> ctor) {
 666         Objects.requireNonNull(ctor);
 667         // fill in vmtarget, vmindex while we have ctor in hand:
 668         MethodHandleNatives.init(this, ctor);
 669         assert(isResolved() && this.clazz != null);
 670         this.name = CONSTRUCTOR_NAME;
 671         if (this.type == null)
 672             this.type = new Object[] { void.class, ctor.getParameterTypes() };






 673     }
 674     /** Create a name for the given reflected field.  The resulting name will be in a resolved state.
 675      */
 676     public MemberName(Field fld) {
 677         this(fld, false);
 678     }
 679     @SuppressWarnings("LeakingThisInConstructor")
 680     public MemberName(Field fld, boolean makeSetter) {
 681         Objects.requireNonNull(fld);
 682         // fill in vmtarget, vmindex while we have fld in hand:
 683         MethodHandleNatives.init(this, fld);
 684         assert(isResolved() && this.clazz != null);
 685         this.name = fld.getName();
 686         this.type = fld.getType();
 687         assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
 688         byte refKind = this.getReferenceKind();
 689         assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
 690         if (makeSetter) {
 691             changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
 692         }


 793     }
 794 
 795     // Construction from symbolic parts, for queries:
 796     /** Create a field or type name from the given components:
 797      *  Declaring class, name, type, reference kind.
 798      *  The declaring class may be supplied as null if this is to be a bare name and type.
 799      *  The resulting name will in an unresolved state.
 800      */
 801     public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
 802         init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
 803         initResolved(false);
 804     }
 805     /** Create a method or constructor name from the given components:
 806      *  Declaring class, name, type, reference kind.
 807      *  It will be a constructor if and only if the name is {@code "<init>"}.
 808      *  The declaring class may be supplied as null if this is to be a bare name and type.
 809      *  The last argument is optional, a boolean which requests REF_invokeSpecial.
 810      *  The resulting name will in an unresolved state.
 811      */
 812     public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
 813         int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
 814         init(defClass, name, type, flagsMods(initFlags, 0, refKind));
 815         initResolved(false);
 816     }
 817     /** Create a method, constructor, or field name from the given components:
 818      *  Reference kind, declaring class, name, type.
 819      */
 820     public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
 821         int kindFlags;
 822         if (MethodHandleNatives.refKindIsField(refKind)) {
 823             kindFlags = IS_FIELD;
 824             if (!(type instanceof Class))
 825                 throw newIllegalArgumentException("not a field type");
 826         } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
 827             kindFlags = IS_METHOD;
 828             if (!(type instanceof MethodType))
 829                 throw newIllegalArgumentException("not a method type");
 830         } else if (refKind == REF_newInvokeSpecial) {
 831             kindFlags = IS_CONSTRUCTOR;
 832             if (!(type instanceof MethodType) ||
 833                 !CONSTRUCTOR_NAME.equals(name))
 834                 throw newIllegalArgumentException("not a constructor type or name");
 835         } else {
 836             throw newIllegalArgumentException("bad reference kind "+refKind);
 837         }
 838         init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
 839         initResolved(false);
 840     }
 841     /** Query whether this member name is resolved to a non-static, non-final method.
 842      */
 843     public boolean hasReceiverTypeDispatch() {
 844         return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
 845     }
 846 
 847     /** Query whether this member name is resolved.
 848      *  A resolved member name is one for which the JVM has found
 849      *  a method, constructor, field, or type binding corresponding exactly to the name.
 850      *  (Document?)
 851      */


 902         }
 903         String name = this.name; // avoid expanding from VM
 904         buf.append(name == null ? "*" : name);
 905         Object type = this.type; // avoid expanding from VM
 906         if (!isInvocable()) {
 907             buf.append('/');
 908             buf.append(type == null ? "*" : getName(type));
 909         } else {
 910             buf.append(type == null ? "(*)*" : getName(type));
 911         }
 912         byte refKind = getReferenceKind();
 913         if (refKind != REF_NONE) {
 914             buf.append('/');
 915             buf.append(MethodHandleNatives.refKindName(refKind));
 916         }
 917         //buf.append("#").append(System.identityHashCode(this));
 918         return buf.toString();
 919     }
 920     private static String getName(Object obj) {
 921         if (obj instanceof Class<?>)
 922             return ((Class<?>)obj).getName();
 923         return String.valueOf(obj);
 924     }
 925 









 926     public IllegalAccessException makeAccessException(String message, Object from) {
 927         message = message + ": "+ toString();
 928         if (from != null)  {
 929             if (from == MethodHandles.publicLookup()) {
 930                 message += ", from public Lookup";
 931             } else {
 932                 Module m;
 933                 if (from instanceof MethodHandles.Lookup) {
 934                     MethodHandles.Lookup lookup = (MethodHandles.Lookup)from;
 935                     m = lookup.lookupClass().getModule();
 936                 } else {
 937                     m = from.getClass().getModule();
 938                 }
 939                 message += ", from " + from + " (" + m + ")";
 940             }
 941         }
 942         return new IllegalAccessException(message);
 943     }
 944     private String message() {
 945         if (isResolved())
 946             return "no access";
 947         else if (isConstructor())
 948             return "no such constructor";
 949         else if (isMethod())
 950             return "no such method";
 951         else
 952             return "no such field";
 953     }
 954     public ReflectiveOperationException makeAccessException() {
 955         String message = message() + ": "+ toString();
 956         ReflectiveOperationException ex;
 957         if (isResolved() || !(resolution instanceof NoSuchMethodError ||
 958                               resolution instanceof NoSuchFieldError))
 959             ex = new IllegalAccessException(message);
 960         else if (isConstructor())
 961             ex = new NoSuchMethodException(message);
 962         else if (isMethod())
 963             ex = new NoSuchMethodException(message);
 964         else
 965             ex = new NoSuchFieldException(message);
 966         if (resolution instanceof Throwable)
 967             ex.initCause((Throwable) resolution);
 968         return ex;
 969     }
 970 
 971     /** Actually making a query requires an access check. */
 972     /*non-public*/ static Factory getFactory() {
 973         return Factory.INSTANCE;
 974     }
 975     /** A factory type for resolving member names with the help of the VM.
 976      *  TBD: Define access-safe public constructors for this factory.
 977      */
 978     /*non-public*/ static class Factory {
 979         private Factory() { } // singleton pattern
 980         static Factory INSTANCE = new Factory();


1118         /** Return a list of all methods defined by the given class.
1119          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1120          *  Access checking is performed on behalf of the given {@code lookupClass}.
1121          *  Inaccessible members are not added to the last.
1122          */
1123         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1124                 Class<?> lookupClass) {
1125             return getMethods(defc, searchSupers, null, null, lookupClass);
1126         }
1127         /** Return a list of matching methods defined by the given class.
1128          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1129          *  Returned methods will match the name (if not null) and the type (if not null).
1130          *  Access checking is performed on behalf of the given {@code lookupClass}.
1131          *  Inaccessible members are not added to the last.
1132          */
1133         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1134                 String name, MethodType type, Class<?> lookupClass) {
1135             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1136             return getMembers(defc, name, type, matchFlags, lookupClass);
1137         }
1138         /** Return a list of all constructors defined by the given class.
1139          *  Access checking is performed on behalf of the given {@code lookupClass}.
1140          *  Inaccessible members are not added to the last.
1141          */
1142         public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
1143             return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
1144         }
1145         /** Return a list of all fields defined by the given class.
1146          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1147          *  Access checking is performed on behalf of the given {@code lookupClass}.
1148          *  Inaccessible members are not added to the last.
1149          */
1150         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1151                 Class<?> lookupClass) {
1152             return getFields(defc, searchSupers, null, null, lookupClass);
1153         }
1154         /** Return a list of all fields defined by the given class.
1155          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1156          *  Returned fields will match the name (if not null) and the type (if not null).
1157          *  Access checking is performed on behalf of the given {@code lookupClass}.
1158          *  Inaccessible members are not added to the last.
1159          */
1160         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1161                 String name, Class<?> type, Class<?> lookupClass) {
1162             int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1163             return getMembers(defc, name, type, matchFlags, lookupClass);
   1 /*
   2  * Copyright (c) 2008, 2019, 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


 174         }
 175         if (!isInvocable()) {
 176             throw newIllegalArgumentException("not invocable, no method type");
 177         }
 178 
 179         // Get a snapshot of type which doesn't get changed by racing threads.
 180         final Object type = this.type;
 181         if (type instanceof String) {
 182             return (String) type;
 183         } else {
 184             return getMethodType().toMethodDescriptorString();
 185         }
 186     }
 187 
 188     /** Return the actual type under which this method or constructor must be invoked.
 189      *  For non-static methods or constructors, this is the type with a leading parameter,
 190      *  a reference to declaring class.  For static methods, it is the same as the declared type.
 191      */
 192     public MethodType getInvocationType() {
 193         MethodType itype = getMethodOrFieldType();
 194         Class<?> c = clazz.asPrimaryType();
 195         if (isObjectConstructor() && getReferenceKind() == REF_newInvokeSpecial)
 196             return itype.changeReturnType(c);
 197         if (!isStatic())
 198             return itype.insertParameterTypes(0, c);
 199         return itype;
 200     }
 201 
 202     /** Utility method producing the parameter types of the method type. */
 203     public Class<?>[] getParameterTypes() {
 204         return getMethodType().parameterArray();
 205     }
 206 
 207     /** Utility method producing the return type of the method type. */
 208     public Class<?> getReturnType() {
 209         return getMethodType().returnType();
 210     }
 211 
 212     /** Return the declared type of this member, which
 213      *  must be a field or type.
 214      *  If it is a type member, that type itself is returned.
 215      */
 216     public Class<?> getFieldType() {
 217         if (type == null) {
 218             expandFromVM();


 268     }
 269 
 270     /** Return the modifier flags of this member.
 271      *  @see java.lang.reflect.Modifier
 272      */
 273     public int getModifiers() {
 274         return (flags & RECOGNIZED_MODIFIERS);
 275     }
 276 
 277     /** Return the reference kind of this member, or zero if none.
 278      */
 279     public byte getReferenceKind() {
 280         return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
 281     }
 282     private boolean referenceKindIsConsistent() {
 283         byte refKind = getReferenceKind();
 284         if (refKind == REF_NONE)  return isType();
 285         if (isField()) {
 286             assert(staticIsConsistent());
 287             assert(MethodHandleNatives.refKindIsField(refKind));
 288         } else if (isObjectConstructor()) {
 289             assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
 290         } else if (isMethod()) {
 291             assert(staticIsConsistent());
 292             assert(MethodHandleNatives.refKindIsMethod(refKind));
 293             if (clazz.isInterface())
 294                 assert(refKind == REF_invokeInterface ||
 295                        refKind == REF_invokeStatic    ||
 296                        refKind == REF_invokeSpecial   ||
 297                        refKind == REF_invokeVirtual && isObjectPublicMethod());
 298         } else {
 299             assert(false);
 300         }
 301         return true;
 302     }
 303     private boolean isObjectPublicMethod() {
 304         if (clazz == Object.class)  return true;
 305         MethodType mtype = getMethodType();
 306         if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
 307             return true;
 308         if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)


 410     private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
 411 
 412     /** Utility method to query the modifier flags of this member. */
 413     public boolean isStatic() {
 414         return Modifier.isStatic(flags);
 415     }
 416     /** Utility method to query the modifier flags of this member. */
 417     public boolean isPublic() {
 418         return Modifier.isPublic(flags);
 419     }
 420     /** Utility method to query the modifier flags of this member. */
 421     public boolean isPrivate() {
 422         return Modifier.isPrivate(flags);
 423     }
 424     /** Utility method to query the modifier flags of this member. */
 425     public boolean isProtected() {
 426         return Modifier.isProtected(flags);
 427     }
 428     /** Utility method to query the modifier flags of this member. */
 429     public boolean isFinal() {
 430         // all fields declared in a value type are effectively final
 431         assert(!clazz.isInlineClass() || !isField() || Modifier.isFinal(flags));
 432         return Modifier.isFinal(flags);
 433     }
 434     /** Utility method to query whether this member or its defining class is final. */
 435     public boolean canBeStaticallyBound() {
 436         return Modifier.isFinal(flags | clazz.getModifiers());
 437     }
 438     /** Utility method to query the modifier flags of this member. */
 439     public boolean isVolatile() {
 440         return Modifier.isVolatile(flags);
 441     }
 442     /** Utility method to query the modifier flags of this member. */
 443     public boolean isAbstract() {
 444         return Modifier.isAbstract(flags);
 445     }
 446     /** Utility method to query the modifier flags of this member. */
 447     public boolean isNative() {
 448         return Modifier.isNative(flags);
 449     }
 450     // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
 451 
 452     // unofficial modifier flags, used by HotSpot:
 453     static final int BRIDGE      = 0x00000040;
 454     static final int VARARGS     = 0x00000080;
 455     static final int SYNTHETIC   = 0x00001000;
 456     static final int ANNOTATION  = 0x00002000;
 457     static final int ENUM        = 0x00004000;
 458     static final int FLATTENED   = 0x00008000;
 459 
 460     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 461     public boolean isBridge() {
 462         return testAllFlags(IS_METHOD | BRIDGE);
 463     }
 464     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 465     public boolean isVarargs() {
 466         return testAllFlags(VARARGS) && isInvocable();
 467     }
 468     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
 469     public boolean isSynthetic() {
 470         return testAllFlags(SYNTHETIC);
 471     }
 472 
 473     /** Query whether this member is a flattened field */
 474     public boolean isFlattened() { return (flags & FLATTENED) == FLATTENED; }
 475 
 476     /** Query whether this member is a field of an inline class. */
 477     public boolean isInlineable()  {
 478         if (isField()) {
 479             Class<?> type = getFieldType();
 480             return type.isInlineClass() && type == type.asPrimaryType();
 481         }
 482         return false;
 483     }
 484 
 485     public boolean isIndirect()  {
 486         if (isField()) {
 487             return getFieldType().isIndirectType();
 488         }
 489         return false;
 490     }
 491 
 492     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
 493 
 494     // modifiers exported by the JVM:
 495     static final int RECOGNIZED_MODIFIERS = 0xFFFF;
 496 
 497     // private flags, not part of RECOGNIZED_MODIFIERS:
 498     static final int
 499             IS_METHOD             = MN_IS_METHOD,              // method (not object constructor)
 500             IS_OBJECT_CONSTRUCTOR = MN_IS_OBJECT_CONSTRUCTOR,  // object constructor
 501             IS_FIELD              = MN_IS_FIELD,               // field
 502             IS_TYPE               = MN_IS_TYPE,                // nested type
 503             CALLER_SENSITIVE      = MN_CALLER_SENSITIVE;       // @CallerSensitive annotation detected
 504 
 505     static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
 506     static final int ALL_KINDS = IS_METHOD | IS_OBJECT_CONSTRUCTOR | IS_FIELD | IS_TYPE;
 507     static final int IS_INVOCABLE = IS_METHOD | IS_OBJECT_CONSTRUCTOR;
 508     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
 509     static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
 510 
 511     /** Utility method to query whether this member is a method or constructor. */
 512     public boolean isInvocable() {
 513         return testAnyFlags(IS_INVOCABLE);
 514     }
 515     /** Utility method to query whether this member is a method, constructor, or field. */
 516     public boolean isFieldOrMethod() {
 517         return testAnyFlags(IS_FIELD_OR_METHOD);
 518     }
 519     /** Query whether this member is a method. */
 520     public boolean isMethod() {
 521         return testAllFlags(IS_METHOD);
 522     }
 523     /** Query whether this member is a constructor. */
 524     public boolean isObjectConstructor() {
 525         return testAllFlags(IS_OBJECT_CONSTRUCTOR);
 526     }
 527     /** Query whether this member is an object constructor or static <init> factory */
 528     public boolean isObjectConstructorOrStaticInitMethod() {
 529         return isObjectConstructor() || (getName().equals(CONSTRUCTOR_NAME) && testAllFlags(IS_METHOD));
 530     }
 531     /** Query whether this member is a field. */
 532     public boolean isField() {
 533         return testAllFlags(IS_FIELD);
 534     }
 535     /** Query whether this member is a type. */
 536     public boolean isType() {
 537         return testAllFlags(IS_TYPE);
 538     }
 539     /** Utility method to query whether this member is neither public, private, nor protected. */
 540     public boolean isPackage() {
 541         return !testAnyFlags(ALL_ACCESS);
 542     }
 543     /** Query whether this member has a CallerSensitive annotation. */
 544     public boolean isCallerSensitive() {
 545         return testAllFlags(CALLER_SENSITIVE);
 546     }
 547 
 548     /** Utility method to query whether this member is accessible from a given lookup class. */
 549     public boolean isAccessibleFrom(Class<?> lookupClass) {


 638                 throw new AbstractMethodError(this.toString());
 639             if (getReferenceKind() == REF_invokeVirtual)
 640                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 641             else if (getReferenceKind() == REF_invokeInterface)
 642                 // invokeSpecial on a default method
 643                 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
 644         }
 645     }
 646     public MemberName asSpecial() {
 647         switch (getReferenceKind()) {
 648         case REF_invokeSpecial:     return this;
 649         case REF_invokeVirtual:     return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
 650         case REF_invokeInterface:   return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
 651         case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
 652         }
 653         throw new IllegalArgumentException(this.toString());
 654     }
 655     /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
 656      *  In that case it must already be REF_invokeSpecial.
 657      */
 658     public MemberName asObjectConstructor() {
 659         switch (getReferenceKind()) {
 660         case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
 661         case REF_newInvokeSpecial:  return this;
 662         }
 663         throw new IllegalArgumentException(this.toString());
 664     }
 665     /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
 666      *  REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
 667      *  The end result is to get a fully virtualized version of the MN.
 668      *  (Note that resolving in the JVM will sometimes devirtualize, changing
 669      *  REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
 670      *  in some corner cases to either of the previous two; this transform
 671      *  undoes that change under the assumption that it occurred.)
 672      */
 673     public MemberName asNormalOriginal() {
 674         byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
 675         byte refKind = getReferenceKind();
 676         byte newRefKind = refKind;
 677         MemberName result = this;
 678         switch (refKind) {
 679         case REF_invokeInterface:
 680         case REF_invokeVirtual:
 681         case REF_invokeSpecial:
 682             newRefKind = normalVirtual;
 683             break;
 684         }
 685         if (newRefKind == refKind)
 686             return this;
 687         result = clone().changeReferenceKind(newRefKind, refKind);
 688         assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
 689         return result;
 690     }
 691     /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
 692     @SuppressWarnings("LeakingThisInConstructor")
 693     public MemberName(Constructor<?> ctor) {
 694         Objects.requireNonNull(ctor);
 695         // fill in vmtarget, vmindex while we have ctor in hand:
 696         MethodHandleNatives.init(this, ctor);
 697         assert(isResolved() && this.clazz != null);
 698         this.name = CONSTRUCTOR_NAME;
 699         if (this.type == null) {
 700             Class<?> rtype = void.class;
 701             if (isStatic()) {  // a static init factory, not a true constructor
 702                 rtype = getDeclaringClass();
 703                 // FIXME: If it's a hidden class, this sig won't work.
 704             }
 705             this.type = new Object[] { rtype, ctor.getParameterTypes() };
 706         }
 707     }
 708     /** Create a name for the given reflected field.  The resulting name will be in a resolved state.
 709      */
 710     public MemberName(Field fld) {
 711         this(fld, false);
 712     }
 713     @SuppressWarnings("LeakingThisInConstructor")
 714     public MemberName(Field fld, boolean makeSetter) {
 715         Objects.requireNonNull(fld);
 716         // fill in vmtarget, vmindex while we have fld in hand:
 717         MethodHandleNatives.init(this, fld);
 718         assert(isResolved() && this.clazz != null);
 719         this.name = fld.getName();
 720         this.type = fld.getType();
 721         assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
 722         byte refKind = this.getReferenceKind();
 723         assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
 724         if (makeSetter) {
 725             changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
 726         }


 827     }
 828 
 829     // Construction from symbolic parts, for queries:
 830     /** Create a field or type name from the given components:
 831      *  Declaring class, name, type, reference kind.
 832      *  The declaring class may be supplied as null if this is to be a bare name and type.
 833      *  The resulting name will in an unresolved state.
 834      */
 835     public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
 836         init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
 837         initResolved(false);
 838     }
 839     /** Create a method or constructor name from the given components:
 840      *  Declaring class, name, type, reference kind.
 841      *  It will be a constructor if and only if the name is {@code "<init>"}.
 842      *  The declaring class may be supplied as null if this is to be a bare name and type.
 843      *  The last argument is optional, a boolean which requests REF_invokeSpecial.
 844      *  The resulting name will in an unresolved state.
 845      */
 846     public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
 847         int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) && type.returnType() == void.class ? IS_OBJECT_CONSTRUCTOR : IS_METHOD);
 848         init(defClass, name, type, flagsMods(initFlags, 0, refKind));
 849         initResolved(false);
 850     }
 851     /** Create a method, constructor, or field name from the given components:
 852      *  Reference kind, declaring class, name, type.
 853      */
 854     public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
 855         int kindFlags;
 856         if (MethodHandleNatives.refKindIsField(refKind)) {
 857             kindFlags = IS_FIELD;
 858             if (!(type instanceof Class))
 859                 throw newIllegalArgumentException("not a field type");
 860         } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
 861             kindFlags = IS_METHOD;
 862             if (!(type instanceof MethodType))
 863                 throw newIllegalArgumentException("not a method type");
 864         } else if (refKind == REF_newInvokeSpecial) {
 865             kindFlags = IS_OBJECT_CONSTRUCTOR;
 866             if (!(type instanceof MethodType) ||
 867                 !CONSTRUCTOR_NAME.equals(name))
 868                 throw newIllegalArgumentException("not a constructor type or name");
 869         } else {
 870             throw newIllegalArgumentException("bad reference kind "+refKind);
 871         }
 872         init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
 873         initResolved(false);
 874     }
 875     /** Query whether this member name is resolved to a non-static, non-final method.
 876      */
 877     public boolean hasReceiverTypeDispatch() {
 878         return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
 879     }
 880 
 881     /** Query whether this member name is resolved.
 882      *  A resolved member name is one for which the JVM has found
 883      *  a method, constructor, field, or type binding corresponding exactly to the name.
 884      *  (Document?)
 885      */


 936         }
 937         String name = this.name; // avoid expanding from VM
 938         buf.append(name == null ? "*" : name);
 939         Object type = this.type; // avoid expanding from VM
 940         if (!isInvocable()) {
 941             buf.append('/');
 942             buf.append(type == null ? "*" : getName(type));
 943         } else {
 944             buf.append(type == null ? "(*)*" : getName(type));
 945         }
 946         byte refKind = getReferenceKind();
 947         if (refKind != REF_NONE) {
 948             buf.append('/');
 949             buf.append(MethodHandleNatives.refKindName(refKind));
 950         }
 951         //buf.append("#").append(System.identityHashCode(this));
 952         return buf.toString();
 953     }
 954     private static String getName(Object obj) {
 955         if (obj instanceof Class<?>)
 956             return toTypeName((Class<?>)obj);
 957         return String.valueOf(obj);
 958     }
 959 
 960     /*
 961      * Returns the class name appended with "?" if it is the nullable projection
 962      * of an inline class.
 963      */
 964     private static String toTypeName(Class<?> type) {
 965         return type.isInlineClass() && type.isIndirectType() ? type.getName() + "?" : type.getName();
 966     }
 967 
 968 
 969     public IllegalAccessException makeAccessException(String message, Object from) {
 970         message = message + ": "+ toString();
 971         if (from != null)  {
 972             if (from == MethodHandles.publicLookup()) {
 973                 message += ", from public Lookup";
 974             } else {
 975                 Module m;
 976                 if (from instanceof MethodHandles.Lookup) {
 977                     MethodHandles.Lookup lookup = (MethodHandles.Lookup)from;
 978                     m = lookup.lookupClass().getModule();
 979                 } else {
 980                     m = from.getClass().getModule();
 981                 }
 982                 message += ", from " + from + " (" + m + ")";
 983             }
 984         }
 985         return new IllegalAccessException(message);
 986     }
 987     private String message() {
 988         if (isResolved())
 989             return "no access";
 990         else if (isObjectConstructor())
 991             return "no such constructor";
 992         else if (isMethod())
 993             return "no such method";
 994         else
 995             return "no such field";
 996     }
 997     public ReflectiveOperationException makeAccessException() {
 998         String message = message() + ": "+ toString();
 999         ReflectiveOperationException ex;
1000         if (isResolved() || !(resolution instanceof NoSuchMethodError ||
1001                               resolution instanceof NoSuchFieldError))
1002             ex = new IllegalAccessException(message);
1003         else if (isObjectConstructor())
1004             ex = new NoSuchMethodException(message);
1005         else if (isMethod())
1006             ex = new NoSuchMethodException(message);
1007         else
1008             ex = new NoSuchFieldException(message);
1009         if (resolution instanceof Throwable)
1010             ex.initCause((Throwable) resolution);
1011         return ex;
1012     }
1013 
1014     /** Actually making a query requires an access check. */
1015     /*non-public*/ static Factory getFactory() {
1016         return Factory.INSTANCE;
1017     }
1018     /** A factory type for resolving member names with the help of the VM.
1019      *  TBD: Define access-safe public constructors for this factory.
1020      */
1021     /*non-public*/ static class Factory {
1022         private Factory() { } // singleton pattern
1023         static Factory INSTANCE = new Factory();


1161         /** Return a list of all methods defined by the given class.
1162          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1163          *  Access checking is performed on behalf of the given {@code lookupClass}.
1164          *  Inaccessible members are not added to the last.
1165          */
1166         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1167                 Class<?> lookupClass) {
1168             return getMethods(defc, searchSupers, null, null, lookupClass);
1169         }
1170         /** Return a list of matching methods defined by the given class.
1171          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1172          *  Returned methods will match the name (if not null) and the type (if not null).
1173          *  Access checking is performed on behalf of the given {@code lookupClass}.
1174          *  Inaccessible members are not added to the last.
1175          */
1176         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1177                 String name, MethodType type, Class<?> lookupClass) {
1178             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1179             return getMembers(defc, name, type, matchFlags, lookupClass);
1180         }
1181         /** Return a list of all object constructors defined by the given class.
1182          *  Access checking is performed on behalf of the given {@code lookupClass}.
1183          *  Inaccessible members are not added to the last.
1184          */
1185         public List<MemberName> getObjectConstructors(Class<?> defc, Class<?> lookupClass) {
1186             return getMembers(defc, null, null, IS_OBJECT_CONSTRUCTOR, lookupClass);
1187         }
1188         /** Return a list of all fields defined by the given class.
1189          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1190          *  Access checking is performed on behalf of the given {@code lookupClass}.
1191          *  Inaccessible members are not added to the last.
1192          */
1193         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1194                 Class<?> lookupClass) {
1195             return getFields(defc, searchSupers, null, null, lookupClass);
1196         }
1197         /** Return a list of all fields defined by the given class.
1198          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
1199          *  Returned fields will match the name (if not null) and the type (if not null).
1200          *  Access checking is performed on behalf of the given {@code lookupClass}.
1201          *  Inaccessible members are not added to the last.
1202          */
1203         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1204                 String name, Class<?> type, Class<?> lookupClass) {
1205             int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1206             return getMembers(defc, name, type, matchFlags, lookupClass);
< prev index next >