Home » openjdk-7 » java.lang.invoke » [javadoc | source]

    1   /*
    2    * Copyright (c) 2008, 2011, 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 java.lang.reflect.Constructor;
   30   import java.lang.reflect.Field;
   31   import java.lang.reflect.Method;
   32   import java.lang.reflect.Member;
   33   import java.lang.reflect.Modifier;
   34   import java.util.ArrayList;
   35   import java.util.Arrays;
   36   import java.util.Collections;
   37   import java.util.Iterator;
   38   import java.util.List;
   39   import static java.lang.invoke.MethodHandleNatives.Constants.*;
   40   import static java.lang.invoke.MethodHandleStatics.*;
   41   
   42   /**
   43    * A {@code MemberName} is a compact symbolic datum which fully characterizes
   44    * a method or field reference.
   45    * A member name refers to a field, method, constructor, or member type.
   46    * Every member name has a simple name (a string) and a type (either a Class or MethodType).
   47    * A member name may also have a non-null declaring class, or it may be simply
   48    * a naked name/type pair.
   49    * A member name may also have non-zero modifier flags.
   50    * Finally, a member name may be either resolved or unresolved.
   51    * If it is resolved, the existence of the named
   52    * <p>
   53    * Whether resolved or not, a member name provides no access rights or
   54    * invocation capability to its possessor.  It is merely a compact
   55    * representation of all symbolic information necessary to link to
   56    * and properly use the named member.
   57    * <p>
   58    * When resolved, a member name's internal implementation may include references to JVM metadata.
   59    * This representation is stateless and only decriptive.
   60    * It provides no private information and no capability to use the member.
   61    * <p>
   62    * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
   63    * about the internals of a method (except its bytecodes) and also
   64    * allows invocation.  A MemberName is much lighter than a Method,
   65    * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
   66    * and those seven fields omit much of the information in Method.
   67    * @author jrose
   68    */
   69   /*non-public*/ final class MemberName implements Member, Cloneable {
   70       private Class<?>   clazz;       // class in which the method is defined
   71       private String     name;        // may be null if not yet materialized
   72       private Object     type;        // may be null if not yet materialized
   73       private int        flags;       // modifier bits; see reflect.Modifier
   74   
   75       private Object     vmtarget;    // VM-specific target value
   76       private int        vmindex;     // method index within class or interface
   77   
   78       { vmindex = VM_INDEX_UNINITIALIZED; }
   79   
   80       /** Return the declaring class of this member.
   81        *  In the case of a bare name and type, the declaring class will be null.
   82        */
   83       public Class<?> getDeclaringClass() {
   84           if (clazz == null && isResolved()) {
   85               expandFromVM();
   86           }
   87           return clazz;
   88       }
   89   
   90       /** Utility method producing the class loader of the declaring class. */
   91       public ClassLoader getClassLoader() {
   92           return clazz.getClassLoader();
   93       }
   94   
   95       /** Return the simple name of this member.
   96        *  For a type, it is the same as {@link Class#getSimpleName}.
   97        *  For a method or field, it is the simple name of the member.
   98        *  For a constructor, it is always {@code "&lt;init&gt;"}.
   99        */
  100       public String getName() {
  101           if (name == null) {
  102               expandFromVM();
  103               if (name == null)  return null;
  104           }
  105           return name;
  106       }
  107   
  108       /** Return the declared type of this member, which
  109        *  must be a method or constructor.
  110        */
  111       public MethodType getMethodType() {
  112           if (type == null) {
  113               expandFromVM();
  114               if (type == null)  return null;
  115           }
  116           if (!isInvocable())
  117               throw newIllegalArgumentException("not invocable, no method type");
  118           if (type instanceof MethodType) {
  119               return (MethodType) type;
  120           }
  121           if (type instanceof String) {
  122               String sig = (String) type;
  123               MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
  124               this.type = res;
  125               return res;
  126           }
  127           if (type instanceof Object[]) {
  128               Object[] typeInfo = (Object[]) type;
  129               Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
  130               Class<?> rtype = (Class<?>) typeInfo[0];
  131               MethodType res = MethodType.methodType(rtype, ptypes);
  132               this.type = res;
  133               return res;
  134           }
  135           throw new InternalError("bad method type "+type);
  136       }
  137   
  138       /** Return the actual type under which this method or constructor must be invoked.
  139        *  For non-static methods or constructors, this is the type with a leading parameter,
  140        *  a reference to declaring class.  For static methods, it is the same as the declared type.
  141        */
  142       public MethodType getInvocationType() {
  143           MethodType itype = getMethodType();
  144           if (!isStatic())
  145               itype = itype.insertParameterTypes(0, clazz);
  146           return itype;
  147       }
  148   
  149       /** Utility method producing the parameter types of the method type. */
  150       public Class<?>[] getParameterTypes() {
  151           return getMethodType().parameterArray();
  152       }
  153   
  154       /** Utility method producing the return type of the method type. */
  155       public Class<?> getReturnType() {
  156           return getMethodType().returnType();
  157       }
  158   
  159       /** Return the declared type of this member, which
  160        *  must be a field or type.
  161        *  If it is a type member, that type itself is returned.
  162        */
  163       public Class<?> getFieldType() {
  164           if (type == null) {
  165               expandFromVM();
  166               if (type == null)  return null;
  167           }
  168           if (isInvocable())
  169               throw newIllegalArgumentException("not a field or nested class, no simple type");
  170           if (type instanceof Class<?>) {
  171               return (Class<?>) type;
  172           }
  173           if (type instanceof String) {
  174               String sig = (String) type;
  175               MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
  176               Class<?> res = mtype.returnType();
  177               this.type = res;
  178               return res;
  179           }
  180           throw new InternalError("bad field type "+type);
  181       }
  182   
  183       /** Utility method to produce either the method type or field type of this member. */
  184       public Object getType() {
  185           return (isInvocable() ? getMethodType() : getFieldType());
  186       }
  187   
  188       /** Utility method to produce the signature of this member,
  189        *  used within the class file format to describe its type.
  190        */
  191       public String getSignature() {
  192           if (type == null) {
  193               expandFromVM();
  194               if (type == null)  return null;
  195           }
  196           if (type instanceof String)
  197               return (String) type;
  198           if (isInvocable())
  199               return BytecodeDescriptor.unparse(getMethodType());
  200           else
  201               return BytecodeDescriptor.unparse(getFieldType());
  202       }
  203   
  204       /** Return the modifier flags of this member.
  205        *  @see java.lang.reflect.Modifier
  206        */
  207       public int getModifiers() {
  208           return (flags & RECOGNIZED_MODIFIERS);
  209       }
  210   
  211       private void setFlags(int flags) {
  212           this.flags = flags;
  213           assert(testAnyFlags(ALL_KINDS));
  214       }
  215   
  216       private boolean testFlags(int mask, int value) {
  217           return (flags & mask) == value;
  218       }
  219       private boolean testAllFlags(int mask) {
  220           return testFlags(mask, mask);
  221       }
  222       private boolean testAnyFlags(int mask) {
  223           return !testFlags(mask, 0);
  224       }
  225   
  226       /** Utility method to query the modifier flags of this member. */
  227       public boolean isStatic() {
  228           return Modifier.isStatic(flags);
  229       }
  230       /** Utility method to query the modifier flags of this member. */
  231       public boolean isPublic() {
  232           return Modifier.isPublic(flags);
  233       }
  234       /** Utility method to query the modifier flags of this member. */
  235       public boolean isPrivate() {
  236           return Modifier.isPrivate(flags);
  237       }
  238       /** Utility method to query the modifier flags of this member. */
  239       public boolean isProtected() {
  240           return Modifier.isProtected(flags);
  241       }
  242       /** Utility method to query the modifier flags of this member. */
  243       public boolean isFinal() {
  244           return Modifier.isFinal(flags);
  245       }
  246       /** Utility method to query the modifier flags of this member. */
  247       public boolean isAbstract() {
  248           return Modifier.isAbstract(flags);
  249       }
  250       // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
  251   
  252       // unofficial modifier flags, used by HotSpot:
  253       static final int BRIDGE    = 0x00000040;
  254       static final int VARARGS   = 0x00000080;
  255       static final int SYNTHETIC = 0x00001000;
  256       static final int ANNOTATION= 0x00002000;
  257       static final int ENUM      = 0x00004000;
  258       /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  259       public boolean isBridge() {
  260           return testAllFlags(IS_METHOD | BRIDGE);
  261       }
  262       /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  263       public boolean isVarargs() {
  264           return testAllFlags(VARARGS) && isInvocable();
  265       }
  266       /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  267       public boolean isSynthetic() {
  268           return testAllFlags(SYNTHETIC);
  269       }
  270   
  271       static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
  272   
  273       // modifiers exported by the JVM:
  274       static final int RECOGNIZED_MODIFIERS = 0xFFFF;
  275   
  276       // private flags, not part of RECOGNIZED_MODIFIERS:
  277       static final int
  278               IS_METHOD      = MN_IS_METHOD,      // method (not constructor)
  279               IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
  280               IS_FIELD       = MN_IS_FIELD,       // field
  281               IS_TYPE        = MN_IS_TYPE;        // nested type
  282       static final int  // for MethodHandleNatives.getMembers
  283               SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
  284               SEARCH_INTERFACES   = MN_SEARCH_INTERFACES;
  285   
  286       static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
  287       static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
  288       static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
  289       static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
  290       static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
  291   
  292       /** Utility method to query whether this member is a method or constructor. */
  293       public boolean isInvocable() {
  294           return testAnyFlags(IS_INVOCABLE);
  295       }
  296       /** Utility method to query whether this member is a method, constructor, or field. */
  297       public boolean isFieldOrMethod() {
  298           return testAnyFlags(IS_FIELD_OR_METHOD);
  299       }
  300       /** Query whether this member is a method. */
  301       public boolean isMethod() {
  302           return testAllFlags(IS_METHOD);
  303       }
  304       /** Query whether this member is a constructor. */
  305       public boolean isConstructor() {
  306           return testAllFlags(IS_CONSTRUCTOR);
  307       }
  308       /** Query whether this member is a field. */
  309       public boolean isField() {
  310           return testAllFlags(IS_FIELD);
  311       }
  312       /** Query whether this member is a type. */
  313       public boolean isType() {
  314           return testAllFlags(IS_TYPE);
  315       }
  316       /** Utility method to query whether this member is neither public, private, nor protected. */
  317       public boolean isPackage() {
  318           return !testAnyFlags(ALL_ACCESS);
  319       }
  320   
  321       /** Initialize a query.   It is not resolved. */
  322       private void init(Class<?> defClass, String name, Object type, int flags) {
  323           // defining class is allowed to be null (for a naked name/type pair)
  324           //name.toString();  // null check
  325           //type.equals(type);  // null check
  326           // fill in fields:
  327           this.clazz = defClass;
  328           this.name = name;
  329           this.type = type;
  330           setFlags(flags);
  331           assert(!isResolved());
  332       }
  333   
  334       private void expandFromVM() {
  335           if (!isResolved())  return;
  336           if (type instanceof Object[])
  337               type = null;  // don't saddle JVM w/ typeInfo
  338           MethodHandleNatives.expand(this);
  339       }
  340   
  341       // Capturing information from the Core Reflection API:
  342       private static int flagsMods(int flags, int mods) {
  343           assert((flags & RECOGNIZED_MODIFIERS) == 0);
  344           assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
  345           return flags | mods;
  346       }
  347       /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
  348       public MemberName(Method m) {
  349           Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
  350           init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
  351           // fill in vmtarget, vmindex while we have m in hand:
  352           MethodHandleNatives.init(this, m);
  353           assert(isResolved());
  354       }
  355       /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
  356       public MemberName(Constructor ctor) {
  357           Object[] typeInfo = { void.class, ctor.getParameterTypes() };
  358           init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
  359           // fill in vmtarget, vmindex while we have ctor in hand:
  360           MethodHandleNatives.init(this, ctor);
  361           assert(isResolved());
  362       }
  363       /** Create a name for the given reflected field.  The resulting name will be in a resolved state. */
  364       public MemberName(Field fld) {
  365           init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
  366           // fill in vmtarget, vmindex while we have fld in hand:
  367           MethodHandleNatives.init(this, fld);
  368           assert(isResolved());
  369       }
  370       /** Create a name for the given class.  The resulting name will be in a resolved state. */
  371       public MemberName(Class<?> type) {
  372           init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
  373           vmindex = 0;  // isResolved
  374           assert(isResolved());
  375       }
  376   
  377       // bare-bones constructor; the JVM will fill it in
  378       MemberName() { }
  379   
  380       // locally useful cloner
  381       @Override protected MemberName clone() {
  382           try {
  383               return (MemberName) super.clone();
  384           } catch (CloneNotSupportedException ex) {
  385               throw new InternalError();
  386           }
  387        }
  388   
  389       // %%% define equals/hashcode?
  390   
  391       // Construction from symbolic parts, for queries:
  392       /** Create a field or type name from the given components:  Declaring class, name, type, modifiers.
  393        *  The declaring class may be supplied as null if this is to be a bare name and type.
  394        *  The resulting name will in an unresolved state.
  395        */
  396       public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
  397           init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
  398       }
  399       /** Create a field or type name from the given components:  Declaring class, name, type.
  400        *  The declaring class may be supplied as null if this is to be a bare name and type.
  401        *  The modifier flags default to zero.
  402        *  The resulting name will in an unresolved state.
  403        */
  404       public MemberName(Class<?> defClass, String name, Class<?> type) {
  405           this(defClass, name, type, 0);
  406       }
  407       /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
  408        *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
  409        *  The declaring class may be supplied as null if this is to be a bare name and type.
  410        *  The resulting name will in an unresolved state.
  411        */
  412       public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
  413           int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
  414           init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
  415       }
  416       /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
  417        *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
  418        *  The declaring class may be supplied as null if this is to be a bare name and type.
  419        *  The modifier flags default to zero.
  420        *  The resulting name will in an unresolved state.
  421        */
  422       public MemberName(Class<?> defClass, String name, MethodType type) {
  423           this(defClass, name, type, 0);
  424       }
  425   
  426       /** Query whether this member name is resolved.
  427        *  A resolved member name is one for which the JVM has found
  428        *  a method, constructor, field, or type binding corresponding exactly to the name.
  429        *  (Document?)
  430        */
  431       public boolean isResolved() {
  432           return (vmindex != VM_INDEX_UNINITIALIZED);
  433       }
  434   
  435       /** Query whether this member name is resolved to a non-static, non-final method.
  436        */
  437       public boolean hasReceiverTypeDispatch() {
  438           return (isMethod() && getVMIndex() >= 0);
  439       }
  440   
  441       /** Produce a string form of this member name.
  442        *  For types, it is simply the type's own string (as reported by {@code toString}).
  443        *  For fields, it is {@code "DeclaringClass.name/type"}.
  444        *  For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
  445        *  If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
  446        *  If the member is unresolved, a prefix {@code "*."} is prepended.
  447        */
  448       @Override
  449       public String toString() {
  450           if (isType())
  451               return type.toString();  // class java.lang.String
  452           // else it is a field, method, or constructor
  453           StringBuilder buf = new StringBuilder();
  454           if (getDeclaringClass() != null) {
  455               buf.append(getName(clazz));
  456               buf.append('.');
  457           }
  458           String name = getName();
  459           buf.append(name == null ? "*" : name);
  460           Object type = getType();
  461           if (!isInvocable()) {
  462               buf.append('/');
  463               buf.append(type == null ? "*" : getName(type));
  464           } else {
  465               buf.append(type == null ? "(*)*" : getName(type));
  466           }
  467           /*
  468           buf.append('/');
  469           // key: Public, private, pRotected, sTatic, Final, sYnchronized,
  470           // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
  471           // (annotation), Enum, (unused)
  472           final String FIELD_MOD_CHARS  = "PprTF?vt????Y?E?";
  473           final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
  474           String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
  475           for (int i = 0; i < modChars.length(); i++) {
  476               if ((flags & (1 << i)) != 0) {
  477                   char mc = modChars.charAt(i);
  478                   if (mc != '?')
  479                       buf.append(mc);
  480               }
  481           }
  482            */
  483           return buf.toString();
  484       }
  485       private static String getName(Object obj) {
  486           if (obj instanceof Class<?>)
  487               return ((Class<?>)obj).getName();
  488           return String.valueOf(obj);
  489       }
  490   
  491       // Queries to the JVM:
  492       /** Document? */
  493       /*non-public*/ int getVMIndex() {
  494           if (!isResolved())
  495               throw newIllegalStateException("not resolved", this);
  496           return vmindex;
  497       }
  498   //    /*non-public*/ Object getVMTarget() {
  499   //        if (!isResolved())
  500   //            throw newIllegalStateException("not resolved", this);
  501   //        return vmtarget;
  502   //    }
  503   
  504       public IllegalAccessException makeAccessException(String message, Object from) {
  505           message = message + ": "+ toString();
  506           if (from != null)  message += ", from " + from;
  507           return new IllegalAccessException(message);
  508       }
  509       private String message() {
  510           if (isResolved())
  511               return "no access";
  512           else if (isConstructor())
  513               return "no such constructor";
  514           else if (isMethod())
  515               return "no such method";
  516           else
  517               return "no such field";
  518       }
  519       public ReflectiveOperationException makeAccessException() {
  520           String message = message() + ": "+ toString();
  521           if (isResolved())
  522               return new IllegalAccessException(message);
  523           else if (isConstructor())
  524               return new NoSuchMethodException(message);
  525           else if (isMethod())
  526               return new NoSuchMethodException(message);
  527           else
  528               return new NoSuchFieldException(message);
  529       }
  530   
  531       /** Actually making a query requires an access check. */
  532       /*non-public*/ static Factory getFactory() {
  533           return Factory.INSTANCE;
  534       }
  535       /** A factory type for resolving member names with the help of the VM.
  536        *  TBD: Define access-safe public constructors for this factory.
  537        */
  538       /*non-public*/ static class Factory {
  539           private Factory() { } // singleton pattern
  540           static Factory INSTANCE = new Factory();
  541   
  542           private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
  543   
  544           /// Queries
  545           List<MemberName> getMembers(Class<?> defc,
  546                   String matchName, Object matchType,
  547                   int matchFlags, Class<?> lookupClass) {
  548               matchFlags &= ALLOWED_FLAGS;
  549               String matchSig = null;
  550               if (matchType != null) {
  551                   matchSig = BytecodeDescriptor.unparse(matchType);
  552                   if (matchSig.startsWith("("))
  553                       matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
  554                   else
  555                       matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
  556               }
  557               final int BUF_MAX = 0x2000;
  558               int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
  559               MemberName[] buf = newMemberBuffer(len1);
  560               int totalCount = 0;
  561               ArrayList<MemberName[]> bufs = null;
  562               int bufCount = 0;
  563               for (;;) {
  564                   bufCount = MethodHandleNatives.getMembers(defc,
  565                           matchName, matchSig, matchFlags,
  566                           lookupClass,
  567                           totalCount, buf);
  568                   if (bufCount <= buf.length) {
  569                       if (bufCount < 0)  bufCount = 0;
  570                       totalCount += bufCount;
  571                       break;
  572                   }
  573                   // JVM returned to us with an intentional overflow!
  574                   totalCount += buf.length;
  575                   int excess = bufCount - buf.length;
  576                   if (bufs == null)  bufs = new ArrayList<MemberName[]>(1);
  577                   bufs.add(buf);
  578                   int len2 = buf.length;
  579                   len2 = Math.max(len2, excess);
  580                   len2 = Math.max(len2, totalCount / 4);
  581                   buf = newMemberBuffer(Math.min(BUF_MAX, len2));
  582               }
  583               ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
  584               if (bufs != null) {
  585                   for (MemberName[] buf0 : bufs) {
  586                       Collections.addAll(result, buf0);
  587                   }
  588               }
  589               result.addAll(Arrays.asList(buf).subList(0, bufCount));
  590               // Signature matching is not the same as type matching, since
  591               // one signature might correspond to several types.
  592               // So if matchType is a Class or MethodType, refilter the results.
  593               if (matchType != null && matchType != matchSig) {
  594                   for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
  595                       MemberName m = it.next();
  596                       if (!matchType.equals(m.getType()))
  597                           it.remove();
  598                   }
  599               }
  600               return result;
  601           }
  602           boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
  603               if (m.name == null || m.type == null) {  // find unique non-overloaded name
  604                   Class<?> defc = m.getDeclaringClass();
  605                   List<MemberName> choices = null;
  606                   if (m.isMethod())
  607                       choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
  608                   else if (m.isConstructor())
  609                       choices = getConstructors(defc, lookupClass);
  610                   else if (m.isField())
  611                       choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
  612                   //System.out.println("resolving "+m+" to "+choices);
  613                   if (choices == null || choices.size() != 1)
  614                       return false;
  615                   if (m.name == null)  m.name = choices.get(0).name;
  616                   if (m.type == null)  m.type = choices.get(0).type;
  617               }
  618               MethodHandleNatives.resolve(m, lookupClass);
  619               if (m.isResolved())  return true;
  620               int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  621               String matchSig = m.getSignature();
  622               MemberName[] buf = { m };
  623               int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
  624                       m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
  625               if (n != 1)  return false;
  626               return m.isResolved();
  627           }
  628           /** Produce a resolved version of the given member.
  629            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  630            *  Access checking is performed on behalf of the given {@code lookupClass}.
  631            *  If lookup fails or access is not permitted, null is returned.
  632            *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
  633            */
  634           public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
  635               MemberName result = m.clone();
  636               if (resolveInPlace(result, searchSupers, lookupClass))
  637                   return result;
  638               return null;
  639           }
  640           /** Produce a resolved version of the given member.
  641            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  642            *  Access checking is performed on behalf of the given {@code lookupClass}.
  643            *  If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
  644            *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
  645            */
  646           public
  647           <NoSuchMemberException extends ReflectiveOperationException>
  648           MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass,
  649                                    Class<NoSuchMemberException> nsmClass)
  650                   throws IllegalAccessException, NoSuchMemberException {
  651               MemberName result = resolveOrNull(m, searchSupers, lookupClass);
  652               if (result != null)
  653                   return result;
  654               ReflectiveOperationException ex = m.makeAccessException();
  655               if (ex instanceof IllegalAccessException)  throw (IllegalAccessException) ex;
  656               throw nsmClass.cast(ex);
  657           }
  658           /** Return a list of all methods defined by the given class.
  659            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  660            *  Access checking is performed on behalf of the given {@code lookupClass}.
  661            *  Inaccessible members are not added to the last.
  662            */
  663           public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
  664                   Class<?> lookupClass) {
  665               return getMethods(defc, searchSupers, null, null, lookupClass);
  666           }
  667           /** Return a list of matching methods defined by the given class.
  668            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  669            *  Returned methods will match the name (if not null) and the type (if not null).
  670            *  Access checking is performed on behalf of the given {@code lookupClass}.
  671            *  Inaccessible members are not added to the last.
  672            */
  673           public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
  674                   String name, MethodType type, Class<?> lookupClass) {
  675               int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  676               return getMembers(defc, name, type, matchFlags, lookupClass);
  677           }
  678           /** Return a list of all constructors defined by the given class.
  679            *  Access checking is performed on behalf of the given {@code lookupClass}.
  680            *  Inaccessible members are not added to the last.
  681            */
  682           public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
  683               return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
  684           }
  685           /** Return a list of all fields defined by the given class.
  686            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  687            *  Access checking is performed on behalf of the given {@code lookupClass}.
  688            *  Inaccessible members are not added to the last.
  689            */
  690           public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
  691                   Class<?> lookupClass) {
  692               return getFields(defc, searchSupers, null, null, lookupClass);
  693           }
  694           /** Return a list of all fields defined by the given class.
  695            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  696            *  Returned fields will match the name (if not null) and the type (if not null).
  697            *  Access checking is performed on behalf of the given {@code lookupClass}.
  698            *  Inaccessible members are not added to the last.
  699            */
  700           public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
  701                   String name, Class<?> type, Class<?> lookupClass) {
  702               int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  703               return getMembers(defc, name, type, matchFlags, lookupClass);
  704           }
  705           /** Return a list of all nested types defined by the given class.
  706            *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  707            *  Access checking is performed on behalf of the given {@code lookupClass}.
  708            *  Inaccessible members are not added to the last.
  709            */
  710           public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
  711                   Class<?> lookupClass) {
  712               int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  713               return getMembers(defc, null, null, matchFlags, lookupClass);
  714           }
  715           private static MemberName[] newMemberBuffer(int length) {
  716               MemberName[] buf = new MemberName[length];
  717               // fill the buffer with dummy structs for the JVM to fill in
  718               for (int i = 0; i < length; i++)
  719                   buf[i] = new MemberName();
  720               return buf;
  721           }
  722       }
  723   
  724   //    static {
  725   //        System.out.println("Hello world!  My methods are:");
  726   //        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
  727   //    }
  728   }

Home » openjdk-7 » java.lang.invoke » [javadoc | source]