jdk/src/share/classes/sun/dyn/MemberName.java
changeset 5722 4ada807383c8
parent 4537 7c3c7f8d5195
child 5725 16c1792b2ee6
equal deleted inserted replaced
5371:ff9031a745d9 5722:4ada807383c8
     1 /*
     1 /*
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2008-2010 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    38 import java.util.Iterator;
    38 import java.util.Iterator;
    39 import java.util.List;
    39 import java.util.List;
    40 import static sun.dyn.MethodHandleNatives.Constants.*;
    40 import static sun.dyn.MethodHandleNatives.Constants.*;
    41 
    41 
    42 /**
    42 /**
    43  * Compact information which fully characterizes a method or field reference.
    43  * A {@code MemberName} is a compact symbolic datum which fully characterizes
    44  * When resolved, it includes a direct pointer to JVM metadata.
    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.
    45  * This representation is stateless and only decriptive.
    59  * This representation is stateless and only decriptive.
    46  * It provides no private information and no capability to use the member.
    60  * It provides no private information and no capability to use the member.
    47  * <p>
    61  * <p>
    48  * By contrast, a java.lang.reflect.Method contains fuller information
    62  * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
    49  * about the internals of a method (except its bytecodes) and also
    63  * about the internals of a method (except its bytecodes) and also
    50  * allows invocation.  A MemberName is much lighter than a reflect.Method,
    64  * allows invocation.  A MemberName is much lighter than a Method,
    51  * since it contains about 7 fields to Method's 16 (plus its sub-arrays),
    65  * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
    52  * and those seven fields omit much of the information in Method.
    66  * and those seven fields omit much of the information in Method.
    53  * @author jrose
    67  * @author jrose
    54  */
    68  */
    55 public final class MemberName implements Member, Cloneable {
    69 public final class MemberName implements Member, Cloneable {
    56     private Class<?>   clazz;       // class in which the method is defined
    70     private Class<?>   clazz;       // class in which the method is defined
    61     private Object     vmtarget;    // VM-specific target value
    75     private Object     vmtarget;    // VM-specific target value
    62     private int        vmindex;     // method index within class or interface
    76     private int        vmindex;     // method index within class or interface
    63 
    77 
    64     { vmindex = VM_INDEX_UNINITIALIZED; }
    78     { vmindex = VM_INDEX_UNINITIALIZED; }
    65 
    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      */
    66     public Class<?> getDeclaringClass() {
    83     public Class<?> getDeclaringClass() {
    67         if (clazz == null && isResolved()) {
    84         if (clazz == null && isResolved()) {
    68             expandFromVM();
    85             expandFromVM();
    69         }
    86         }
    70         return clazz;
    87         return clazz;
    71     }
    88     }
    72 
    89 
       
    90     /** Utility method producing the class loader of the declaring class. */
    73     public ClassLoader getClassLoader() {
    91     public ClassLoader getClassLoader() {
    74         return clazz.getClassLoader();
    92         return clazz.getClassLoader();
    75     }
    93     }
    76 
    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      */
    77     public String getName() {
   100     public String getName() {
    78         if (name == null) {
   101         if (name == null) {
    79             expandFromVM();
   102             expandFromVM();
    80             if (name == null)  return null;
   103             if (name == null)  return null;
    81         }
   104         }
    82         return name;
   105         return name;
    83     }
   106     }
    84 
   107 
       
   108     /** Return the declared type of this member, which
       
   109      *  must be a method or constructor.
       
   110      */
    85     public MethodType getMethodType() {
   111     public MethodType getMethodType() {
    86         if (type == null) {
   112         if (type == null) {
    87             expandFromVM();
   113             expandFromVM();
    88             if (type == null)  return null;
   114             if (type == null)  return null;
    89         }
   115         }
   107             return res;
   133             return res;
   108         }
   134         }
   109         throw new InternalError("bad method type "+type);
   135         throw new InternalError("bad method type "+type);
   110     }
   136     }
   111 
   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      */
   112     public MethodType getInvocationType() {
   142     public MethodType getInvocationType() {
   113         MethodType itype = getMethodType();
   143         MethodType itype = getMethodType();
   114         if (!isStatic())
   144         if (!isStatic())
   115             itype = itype.insertParameterTypes(0, clazz);
   145             itype = itype.insertParameterTypes(0, clazz);
   116         return itype;
   146         return itype;
   117     }
   147     }
   118 
   148 
       
   149     /** Utility method producing the parameter types of the method type. */
   119     public Class<?>[] getParameterTypes() {
   150     public Class<?>[] getParameterTypes() {
   120         return getMethodType().parameterArray();
   151         return getMethodType().parameterArray();
   121     }
   152     }
   122 
   153 
       
   154     /** Utility method producing the return type of the method type. */
   123     public Class<?> getReturnType() {
   155     public Class<?> getReturnType() {
   124         return getMethodType().returnType();
   156         return getMethodType().returnType();
   125     }
   157     }
   126 
   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      */
   127     public Class<?> getFieldType() {
   163     public Class<?> getFieldType() {
   128         if (type == null) {
   164         if (type == null) {
   129             expandFromVM();
   165             expandFromVM();
   130             if (type == null)  return null;
   166             if (type == null)  return null;
   131         }
   167         }
   142             return res;
   178             return res;
   143         }
   179         }
   144         throw new InternalError("bad field type "+type);
   180         throw new InternalError("bad field type "+type);
   145     }
   181     }
   146 
   182 
       
   183     /** Utility method to produce either the method type or field type of this member. */
   147     public Object getType() {
   184     public Object getType() {
   148         return (isInvocable() ? getMethodType() : getFieldType());
   185         return (isInvocable() ? getMethodType() : getFieldType());
   149     }
   186     }
   150 
   187 
       
   188     /** Utility method to produce the signature of this member,
       
   189      *  used within the class file format to describe its type.
       
   190      */
   151     public String getSignature() {
   191     public String getSignature() {
   152         if (type == null) {
   192         if (type == null) {
   153             expandFromVM();
   193             expandFromVM();
   154             if (type == null)  return null;
   194             if (type == null)  return null;
   155         }
   195         }
   159             return BytecodeDescriptor.unparse(getMethodType());
   199             return BytecodeDescriptor.unparse(getMethodType());
   160         else
   200         else
   161             return BytecodeDescriptor.unparse(getFieldType());
   201             return BytecodeDescriptor.unparse(getFieldType());
   162     }
   202     }
   163 
   203 
       
   204     /** Return the modifier flags of this member.
       
   205      *  @see java.lang.reflect.Modifier
       
   206      */
   164     public int getModifiers() {
   207     public int getModifiers() {
   165         return (flags & RECOGNIZED_MODIFIERS);
   208         return (flags & RECOGNIZED_MODIFIERS);
   166     }
   209     }
   167 
   210 
   168     private void setFlags(int flags) {
   211     private void setFlags(int flags) {
   178     }
   221     }
   179     private boolean testAnyFlags(int mask) {
   222     private boolean testAnyFlags(int mask) {
   180         return !testFlags(mask, 0);
   223         return !testFlags(mask, 0);
   181     }
   224     }
   182 
   225 
       
   226     /** Utility method to query the modifier flags of this member. */
   183     public boolean isStatic() {
   227     public boolean isStatic() {
   184         return Modifier.isStatic(flags);
   228         return Modifier.isStatic(flags);
   185     }
   229     }
       
   230     /** Utility method to query the modifier flags of this member. */
   186     public boolean isPublic() {
   231     public boolean isPublic() {
   187         return Modifier.isPublic(flags);
   232         return Modifier.isPublic(flags);
   188     }
   233     }
       
   234     /** Utility method to query the modifier flags of this member. */
   189     public boolean isPrivate() {
   235     public boolean isPrivate() {
   190         return Modifier.isPrivate(flags);
   236         return Modifier.isPrivate(flags);
   191     }
   237     }
       
   238     /** Utility method to query the modifier flags of this member. */
   192     public boolean isProtected() {
   239     public boolean isProtected() {
   193         return Modifier.isProtected(flags);
   240         return Modifier.isProtected(flags);
   194     }
   241     }
       
   242     /** Utility method to query the modifier flags of this member. */
   195     public boolean isFinal() {
   243     public boolean isFinal() {
   196         return Modifier.isFinal(flags);
   244         return Modifier.isFinal(flags);
   197     }
   245     }
       
   246     /** Utility method to query the modifier flags of this member. */
   198     public boolean isAbstract() {
   247     public boolean isAbstract() {
   199         return Modifier.isAbstract(flags);
   248         return Modifier.isAbstract(flags);
   200     }
   249     }
   201     // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
   250     // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
   202 
   251 
   204     static final int BRIDGE    = 0x00000040;
   253     static final int BRIDGE    = 0x00000040;
   205     static final int VARARGS   = 0x00000080;
   254     static final int VARARGS   = 0x00000080;
   206     static final int SYNTHETIC = 0x00001000;
   255     static final int SYNTHETIC = 0x00001000;
   207     static final int ANNOTATION= 0x00002000;
   256     static final int ANNOTATION= 0x00002000;
   208     static final int ENUM      = 0x00004000;
   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. */
   209     public boolean isBridge() {
   259     public boolean isBridge() {
   210         return testAllFlags(IS_METHOD | BRIDGE);
   260         return testAllFlags(IS_METHOD | BRIDGE);
   211     }
   261     }
       
   262     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
   212     public boolean isVarargs() {
   263     public boolean isVarargs() {
   213         return testAllFlags(VARARGS) && isInvocable();
   264         return testAllFlags(VARARGS) && isInvocable();
   214     }
   265     }
       
   266     /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
   215     public boolean isSynthetic() {
   267     public boolean isSynthetic() {
   216         return testAllFlags(SYNTHETIC);
   268         return testAllFlags(SYNTHETIC);
   217     }
   269     }
   218 
   270 
   219     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
   271     static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
   235     static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
   287     static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
   236     static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
   288     static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
   237     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
   289     static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
   238     static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
   290     static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
   239 
   291 
       
   292     /** Utility method to query whether this member is a method or constructor. */
   240     public boolean isInvocable() {
   293     public boolean isInvocable() {
   241         return testAnyFlags(IS_INVOCABLE);
   294         return testAnyFlags(IS_INVOCABLE);
   242     }
   295     }
       
   296     /** Utility method to query whether this member is a method, constructor, or field. */
   243     public boolean isFieldOrMethod() {
   297     public boolean isFieldOrMethod() {
   244         return testAnyFlags(IS_FIELD_OR_METHOD);
   298         return testAnyFlags(IS_FIELD_OR_METHOD);
   245     }
   299     }
       
   300     /** Query whether this member is a method. */
   246     public boolean isMethod() {
   301     public boolean isMethod() {
   247         return testAllFlags(IS_METHOD);
   302         return testAllFlags(IS_METHOD);
   248     }
   303     }
       
   304     /** Query whether this member is a constructor. */
   249     public boolean isConstructor() {
   305     public boolean isConstructor() {
   250         return testAllFlags(IS_CONSTRUCTOR);
   306         return testAllFlags(IS_CONSTRUCTOR);
   251     }
   307     }
       
   308     /** Query whether this member is a field. */
   252     public boolean isField() {
   309     public boolean isField() {
   253         return testAllFlags(IS_FIELD);
   310         return testAllFlags(IS_FIELD);
   254     }
   311     }
       
   312     /** Query whether this member is a type. */
   255     public boolean isType() {
   313     public boolean isType() {
   256         return testAllFlags(IS_TYPE);
   314         return testAllFlags(IS_TYPE);
   257     }
   315     }
       
   316     /** Utility method to query whether this member is neither public, private, nor protected. */
   258     public boolean isPackage() {
   317     public boolean isPackage() {
   259         return !testAnyFlags(ALL_ACCESS);
   318         return !testAnyFlags(ALL_ACCESS);
   260     }
   319     }
   261 
   320 
   262     /** Initialize a query.   It is not resolved. */
   321     /** Initialize a query.   It is not resolved. */
   263     private void init(Class<?> defClass, String name, Object type, int flags) {
   322     private void init(Class<?> defClass, String name, Object type, int flags) {
   264         // defining class is allowed to be null (for a naked name/type pair)
   323         // defining class is allowed to be null (for a naked name/type pair)
   265         name.toString();  // null check
   324         //name.toString();  // null check
   266         type.equals(type);  // null check
   325         //type.equals(type);  // null check
   267         // fill in fields:
   326         // fill in fields:
   268         this.clazz = defClass;
   327         this.clazz = defClass;
   269         this.name = name;
   328         this.name = name;
   270         this.type = type;
   329         this.type = type;
   271         setFlags(flags);
   330         setFlags(flags);
   283     private static int flagsMods(int flags, int mods) {
   342     private static int flagsMods(int flags, int mods) {
   284         assert((flags & RECOGNIZED_MODIFIERS) == 0);
   343         assert((flags & RECOGNIZED_MODIFIERS) == 0);
   285         assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
   344         assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
   286         return flags | mods;
   345         return flags | mods;
   287     }
   346     }
       
   347     /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
   288     public MemberName(Method m) {
   348     public MemberName(Method m) {
   289         Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
   349         Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
   290         init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
   350         init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
   291         // fill in vmtarget, vmindex while we have m in hand:
   351         // fill in vmtarget, vmindex while we have m in hand:
   292         MethodHandleNatives.init(this, m);
   352         MethodHandleNatives.init(this, m);
   293         assert(isResolved());
   353         assert(isResolved());
   294     }
   354     }
       
   355     /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
   295     public MemberName(Constructor ctor) {
   356     public MemberName(Constructor ctor) {
   296         Object[] typeInfo = { void.class, ctor.getParameterTypes() };
   357         Object[] typeInfo = { void.class, ctor.getParameterTypes() };
   297         init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
   358         init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
   298         // fill in vmtarget, vmindex while we have ctor in hand:
   359         // fill in vmtarget, vmindex while we have ctor in hand:
   299         MethodHandleNatives.init(this, ctor);
   360         MethodHandleNatives.init(this, ctor);
   300         assert(isResolved());
   361         assert(isResolved());
   301     }
   362     }
       
   363     /** Create a name for the given reflected field.  The resulting name will be in a resolved state. */
   302     public MemberName(Field fld) {
   364     public MemberName(Field fld) {
   303         init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
   365         init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
   304         // fill in vmtarget, vmindex while we have fld in hand:
   366         // fill in vmtarget, vmindex while we have fld in hand:
   305         MethodHandleNatives.init(this, fld);
   367         MethodHandleNatives.init(this, fld);
   306         assert(isResolved());
   368         assert(isResolved());
   307     }
   369     }
       
   370     /** Create a name for the given class.  The resulting name will be in a resolved state. */
   308     public MemberName(Class<?> type) {
   371     public MemberName(Class<?> type) {
   309         init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
   372         init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
   310         vmindex = 0;  // isResolved
   373         vmindex = 0;  // isResolved
   311         assert(isResolved());
   374         assert(isResolved());
   312     }
   375     }
   324      }
   387      }
   325 
   388 
   326     // %%% define equals/hashcode?
   389     // %%% define equals/hashcode?
   327 
   390 
   328     // Construction from symbolic parts, for queries:
   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      */
   329     public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
   396     public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
   330         init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
   397         init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
   331     }
   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      */
   332     public MemberName(Class<?> defClass, String name, Class<?> type) {
   404     public MemberName(Class<?> defClass, String name, Class<?> type) {
   333         this(defClass, name, type, 0);
   405         this(defClass, name, type, 0);
   334     }
   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      */
   335     public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
   412     public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
   336         int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
   413         int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
   337         init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
   414         init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
   338     }
   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      */
   339     public MemberName(Class<?> defClass, String name, MethodType type) {
   422     public MemberName(Class<?> defClass, String name, MethodType type) {
   340         this(defClass, name, type, 0);
   423         this(defClass, name, type, 0);
   341     }
   424     }
   342 
   425 
   343     boolean isResolved() {
   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() {
   344         return (vmindex != VM_INDEX_UNINITIALIZED);
   432         return (vmindex != VM_INDEX_UNINITIALIZED);
   345     }
   433     }
   346 
   434 
       
   435     /** Query whether this member name is resolved to a non-static, non-final method.
       
   436      */
   347     public boolean hasReceiverTypeDispatch() {
   437     public boolean hasReceiverTypeDispatch() {
   348         return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
   438         return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
   349     }
   439     }
   350 
   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      */
   351     @Override
   448     @Override
   352     public String toString() {
   449     public String toString() {
   353         if (isType())
   450         if (isType())
   354             return type.toString();  // class java.lang.String
   451             return type.toString();  // class java.lang.String
   355         // else it is a field, method, or constructor
   452         // else it is a field, method, or constructor
   358             buf.append("*.");
   455             buf.append("*.");
   359         if (getDeclaringClass() != null) {
   456         if (getDeclaringClass() != null) {
   360             buf.append(getName(clazz));
   457             buf.append(getName(clazz));
   361             buf.append('.');
   458             buf.append('.');
   362         }
   459         }
   363         buf.append(getName());
   460         String name = getName();
   364         if (!isInvocable())  buf.append('/');
   461         buf.append(name == null ? "*" : name);
   365         buf.append(getName(getType()));
   462         Object type = getType();
       
   463         if (!isInvocable()) {
       
   464             buf.append('/');
       
   465             buf.append(type == null ? "*" : getName(type));
       
   466         } else {
       
   467             buf.append(type == null ? "(*)*" : getName(type));
       
   468         }
   366         /*
   469         /*
   367         buf.append('/');
   470         buf.append('/');
   368         // key: Public, private, pRotected, sTatic, Final, sYnchronized,
   471         // key: Public, private, pRotected, sTatic, Final, sYnchronized,
   369         // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
   472         // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
   370         // (annotation), Enum, (unused)
   473         // (annotation), Enum, (unused)
   372         final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
   475         final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
   373         String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
   476         String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
   374         for (int i = 0; i < modChars.length(); i++) {
   477         for (int i = 0; i < modChars.length(); i++) {
   375             if ((flags & (1 << i)) != 0) {
   478             if ((flags & (1 << i)) != 0) {
   376                 char mc = modChars.charAt(i);
   479                 char mc = modChars.charAt(i);
   377                 if (mc != '.')
   480                 if (mc != '?')
   378                     buf.append(mc);
   481                     buf.append(mc);
   379             }
   482             }
   380         }
   483         }
   381          */
   484          */
   382         return buf.toString();
   485         return buf.toString();
   386             return ((Class<?>)obj).getName();
   489             return ((Class<?>)obj).getName();
   387         return String.valueOf(obj);
   490         return String.valueOf(obj);
   388     }
   491     }
   389 
   492 
   390     // Queries to the JVM:
   493     // Queries to the JVM:
       
   494     /** Document? */
   391     public int getVMIndex(Access token) {
   495     public int getVMIndex(Access token) {
   392         Access.check(token);
   496         Access.check(token);
   393         if (!isResolved())
   497         if (!isResolved())
   394             throw newIllegalStateException("not resolved");
   498             throw newIllegalStateException("not resolved");
   395         return vmindex;
   499         return vmindex;
   409         return new IllegalArgumentException(message);
   513         return new IllegalArgumentException(message);
   410     }
   514     }
   411     public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) {
   515     public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) {
   412         return newNoAccessException("cannot access", name, lookupClass);
   516         return newNoAccessException("cannot access", name, lookupClass);
   413     }
   517     }
   414     public static NoAccessException newNoAccessException(MemberName name, MethodHandles.Lookup lookup) {
       
   415         return newNoAccessException(name, lookup.lookupClass());
       
   416     }
       
   417     public static NoAccessException newNoAccessException(String message,
   518     public static NoAccessException newNoAccessException(String message,
   418             MemberName name, Class<?> lookupClass) {
   519             MemberName name, Class<?> lookupClass) {
   419         message += ": " + name;
   520         message += ": " + name;
   420         if (lookupClass != null)  message += ", from " + lookupClass.getName();
   521         if (lookupClass != null)  message += ", from " + lookupClass.getName();
   421         return new NoAccessException(message);
   522         return new NoAccessException(message);
   427         return Factory.INSTANCE;
   528         return Factory.INSTANCE;
   428     }
   529     }
   429     public static Factory getFactory() {
   530     public static Factory getFactory() {
   430         return getFactory(Access.getToken());
   531         return getFactory(Access.getToken());
   431     }
   532     }
       
   533     /** A factory type for resolving member names with the help of the VM.
       
   534      *  TBD: Define access-safe public constructors for this factory.
       
   535      */
   432     public static class Factory {
   536     public static class Factory {
   433         private Factory() { } // singleton pattern
   537         private Factory() { } // singleton pattern
   434         static Factory INSTANCE = new Factory();
   538         static Factory INSTANCE = new Factory();
   435 
   539 
   436         private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
   540         private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
   492                 }
   596                 }
   493             }
   597             }
   494             return result;
   598             return result;
   495         }
   599         }
   496         boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
   600         boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
       
   601             if (m.name == null || m.type == null) {  // find unique non-overloaded name
       
   602                 Class<?> defc = m.getDeclaringClass();
       
   603                 List<MemberName> choices = null;
       
   604                 if (m.isMethod())
       
   605                     choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
       
   606                 else if (m.isConstructor())
       
   607                     choices = getConstructors(defc, lookupClass);
       
   608                 else if (m.isField())
       
   609                     choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
       
   610                 //System.out.println("resolving "+m+" to "+choices);
       
   611                 if (choices == null || choices.size() != 1)
       
   612                     return false;
       
   613                 if (m.name == null)  m.name = choices.get(0).name;
       
   614                 if (m.type == null)  m.type = choices.get(0).type;
       
   615             }
   497             MethodHandleNatives.resolve(m, lookupClass);
   616             MethodHandleNatives.resolve(m, lookupClass);
   498             if (m.isResolved())  return true;
   617             if (m.isResolved())  return true;
   499             int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   618             int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   500             String matchSig = m.getSignature();
   619             String matchSig = m.getSignature();
   501             MemberName[] buf = { m };
   620             MemberName[] buf = { m };
   502             int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
   621             int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
   503                     m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
   622                     m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
   504             if (n != 1)  return false;
   623             if (n != 1)  return false;
   505             return m.isResolved();
   624             return m.isResolved();
   506         }
   625         }
       
   626         /** Produce a resolved version of the given member.
       
   627          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   628          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   629          *  If lookup fails or access is not permitted, null is returned.
       
   630          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
       
   631          */
   507         public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
   632         public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
   508             MemberName result = m.clone();
   633             MemberName result = m.clone();
   509             if (resolveInPlace(result, searchSupers, lookupClass))
   634             if (resolveInPlace(result, searchSupers, lookupClass))
   510                 return result;
   635                 return result;
   511             return null;
   636             return null;
   512         }
   637         }
       
   638         /** Produce a resolved version of the given member.
       
   639          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   640          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   641          *  If lookup fails or access is not permitted, a {@linkplain NoAccessException} is thrown.
       
   642          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
       
   643          */
   513         public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) {
   644         public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) {
   514             MemberName result = resolveOrNull(m, searchSupers, lookupClass);
   645             MemberName result = resolveOrNull(m, searchSupers, lookupClass);
   515             if (result != null)
   646             if (result != null)
   516                 return result;
   647                 return result;
   517             throw newNoAccessException(m, lookupClass);
   648             throw newNoAccessException(m, lookupClass);
   518         }
   649         }
       
   650         /** Return a list of all methods defined by the given class.
       
   651          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   652          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   653          *  Inaccessible members are not added to the last.
       
   654          */
   519         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
   655         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
   520                 Class<?> lookupClass) {
   656                 Class<?> lookupClass) {
   521             return getMethods(defc, searchSupers, null, null, lookupClass);
   657             return getMethods(defc, searchSupers, null, null, lookupClass);
   522         }
   658         }
       
   659         /** Return a list of matching methods defined by the given class.
       
   660          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   661          *  Returned methods will match the name (if not null) and the type (if not null).
       
   662          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   663          *  Inaccessible members are not added to the last.
       
   664          */
   523         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
   665         public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
   524                 String name, MethodType type, Class<?> lookupClass) {
   666                 String name, MethodType type, Class<?> lookupClass) {
   525             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   667             int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   526             return getMembers(defc, name, type, matchFlags, lookupClass);
   668             return getMembers(defc, name, type, matchFlags, lookupClass);
   527         }
   669         }
       
   670         /** Return a list of all constructors defined by the given class.
       
   671          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   672          *  Inaccessible members are not added to the last.
       
   673          */
   528         public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
   674         public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
   529             return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
   675             return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
   530         }
   676         }
       
   677         /** Return a list of all fields defined by the given class.
       
   678          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   679          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   680          *  Inaccessible members are not added to the last.
       
   681          */
   531         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
   682         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
   532                 Class<?> lookupClass) {
   683                 Class<?> lookupClass) {
   533             return getFields(defc, searchSupers, null, null, lookupClass);
   684             return getFields(defc, searchSupers, null, null, lookupClass);
   534         }
   685         }
       
   686         /** Return a list of all fields defined by the given class.
       
   687          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   688          *  Returned fields will match the name (if not null) and the type (if not null).
       
   689          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   690          *  Inaccessible members are not added to the last.
       
   691          */
   535         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
   692         public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
   536                 String name, Class<?> type, Class<?> lookupClass) {
   693                 String name, Class<?> type, Class<?> lookupClass) {
   537             int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   694             int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   538             return getMembers(defc, name, type, matchFlags, lookupClass);
   695             return getMembers(defc, name, type, matchFlags, lookupClass);
   539         }
   696         }
       
   697         /** Return a list of all nested types defined by the given class.
       
   698          *  Super types are searched (for inherited members) if {@code searchSupers} is true.
       
   699          *  Access checking is performed on behalf of the given {@code lookupClass}.
       
   700          *  Inaccessible members are not added to the last.
       
   701          */
   540         public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
   702         public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
   541                 Class<?> lookupClass) {
   703                 Class<?> lookupClass) {
   542             int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   704             int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
   543             return getMembers(defc, null, null, matchFlags, lookupClass);
   705             return getMembers(defc, null, null, matchFlags, lookupClass);
   544         }
   706         }