MemberName.java revision 10471:d56a71cf0b9e
118334Speter/* 290075Sobrien * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3117395Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 418334Speter * 590075Sobrien * This code is free software; you can redistribute it and/or modify it 618334Speter * under the terms of the GNU General Public License version 2 only, as 790075Sobrien * published by the Free Software Foundation. Oracle designates this 890075Sobrien * particular file as subject to the "Classpath" exception as provided 990075Sobrien * by Oracle in the LICENSE file that accompanied this code. 1090075Sobrien * 1118334Speter * This code is distributed in the hope that it will be useful, but WITHOUT 1290075Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1390075Sobrien * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1490075Sobrien * version 2 for more details (a copy is included in the LICENSE file that 1590075Sobrien * accompanied this code). 1618334Speter * 1718334Speter * You should have received a copy of the GNU General Public License version 1890075Sobrien * 2 along with this work; if not, write to the Free Software Foundation, 1990075Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2090075Sobrien * 2118334Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2218334Speter * or visit www.oracle.com if you need additional information or have any 2350397Sobrien * questions. 2450397Sobrien */ 2550397Sobrien 2650397Sobrienpackage java.lang.invoke; 2750397Sobrien 2890075Sobrienimport sun.invoke.util.BytecodeDescriptor; 2990075Sobrienimport sun.invoke.util.VerifyAccess; 3050397Sobrien 3150397Sobrienimport java.lang.reflect.Constructor; 3250397Sobrienimport java.lang.reflect.Field; 3390075Sobrienimport java.lang.reflect.Method; 3490075Sobrienimport java.lang.reflect.Member; 3590075Sobrienimport java.lang.reflect.Modifier; 36117395Skanimport java.util.ArrayList; 37117395Skanimport java.util.Arrays; 38117395Skanimport java.util.Collections; 3918334Speterimport java.util.Iterator; 4090075Sobrienimport java.util.List; 4190075Sobrienimport static java.lang.invoke.MethodHandleNatives.Constants.*; 4252284Sobrienimport static java.lang.invoke.MethodHandleStatics.*; 4352284Sobrienimport java.util.Objects; 4418334Speter 4518334Speter/** 4618334Speter * A {@code MemberName} is a compact symbolic datum which fully characterizes 4718334Speter * a method or field reference. 4818334Speter * A member name refers to a field, method, constructor, or member type. 4918334Speter * Every member name has a simple name (a string) and a type (either a Class or MethodType). 5018334Speter * A member name may also have a non-null declaring class, or it may be simply 5118334Speter * a naked name/type pair. 52107590Sobrien * A member name may also have non-zero modifier flags. 5318334Speter * Finally, a member name may be either resolved or unresolved. 5490075Sobrien * If it is resolved, the existence of the named 5518334Speter * <p> 56107590Sobrien * Whether resolved or not, a member name provides no access rights or 5718334Speter * invocation capability to its possessor. It is merely a compact 5818334Speter * representation of all symbolic information necessary to link to 5918334Speter * and properly use the named member. 6090075Sobrien * <p> 6190075Sobrien * When resolved, a member name's internal implementation may include references to JVM metadata. 6290075Sobrien * This representation is stateless and only descriptive. 6390075Sobrien * It provides no private information and no capability to use the member. 6490075Sobrien * <p> 6590075Sobrien * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information 6690075Sobrien * about the internals of a method (except its bytecodes) and also 6790075Sobrien * allows invocation. A MemberName is much lighter than a Method, 6852284Sobrien * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), 6952284Sobrien * and those seven fields omit much of the information in Method. 7018334Speter * @author jrose 7118334Speter */ 7218334Speter/*non-public*/ final class MemberName implements Member, Cloneable { 7318334Speter private Class<?> clazz; // class in which the method is defined 7418334Speter private String name; // may be null if not yet materialized 7518334Speter private Object type; // may be null if not yet materialized 7618334Speter private int flags; // modifier bits; see reflect.Modifier 7718334Speter //@Injected JVM_Method* vmtarget; 7818334Speter //@Injected int vmindex; 7918334Speter private Object resolution; // if null, this guy is resolved 8018334Speter 8118334Speter /** Return the declaring class of this member. 8218334Speter * In the case of a bare name and type, the declaring class will be null. 8318334Speter */ 8450397Sobrien public Class<?> getDeclaringClass() { 8518334Speter return clazz; 8618334Speter } 8790075Sobrien 8890075Sobrien /** Utility method producing the class loader of the declaring class. */ 8990075Sobrien public ClassLoader getClassLoader() { 9090075Sobrien return clazz.getClassLoader(); 9118334Speter } 9218334Speter 9318334Speter /** Return the simple name of this member. 9418334Speter * For a type, it is the same as {@link Class#getSimpleName}. 9518334Speter * For a method or field, it is the simple name of the member. 9618334Speter * For a constructor, it is always {@code "<init>"}. 97117395Skan */ 9818334Speter public String getName() { 9918334Speter if (name == null) { 10018334Speter expandFromVM(); 10118334Speter if (name == null) { 10218334Speter return null; 10318334Speter } 10418334Speter } 10518334Speter return name; 10618334Speter } 10718334Speter 10818334Speter public MethodType getMethodOrFieldType() { 10918334Speter if (isInvocable()) 11018334Speter return getMethodType(); 11118334Speter if (isGetter()) 11218334Speter return MethodType.methodType(getFieldType()); 11318334Speter if (isSetter()) 11418334Speter return MethodType.methodType(void.class, getFieldType()); 11518334Speter throw new InternalError("not a method or field: "+this); 11618334Speter } 11718334Speter 11818334Speter /** Return the declared type of this member, which 11918334Speter * must be a method or constructor. 12018334Speter */ 12118334Speter public MethodType getMethodType() { 12218334Speter if (type == null) { 12318334Speter expandFromVM(); 12418334Speter if (type == null) { 12518334Speter return null; 12618334Speter } 12790075Sobrien } 12890075Sobrien if (!isInvocable()) { 12990075Sobrien throw newIllegalArgumentException("not invocable, no method type"); 13018334Speter } 13118334Speter 132117395Skan { 13318334Speter // Get a snapshot of type which doesn't get changed by racing threads. 13418334Speter final Object type = this.type; 13518334Speter if (type instanceof MethodType) { 13618334Speter return (MethodType) type; 13718334Speter } 13818334Speter } 13918334Speter 14018334Speter // type is not a MethodType yet. Convert it thread-safely. 14190075Sobrien synchronized (this) { 14290075Sobrien if (type instanceof String) { 14390075Sobrien String sig = (String) type; 14490075Sobrien MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader()); 14590075Sobrien type = res; 14690075Sobrien } else if (type instanceof Object[]) { 14790075Sobrien Object[] typeInfo = (Object[]) type; 14818334Speter Class<?>[] ptypes = (Class<?>[]) typeInfo[1]; 14918334Speter Class<?> rtype = (Class<?>) typeInfo[0]; 15018334Speter MethodType res = MethodType.methodType(rtype, ptypes); 15118334Speter type = res; 15218334Speter } 15318334Speter // Make sure type is a MethodType for racing threads. 15418334Speter assert type instanceof MethodType : "bad method type " + type; 15590075Sobrien } 15690075Sobrien return (MethodType) type; 15752284Sobrien } 15890075Sobrien 15990075Sobrien /** Return the actual type under which this method or constructor must be invoked. 16090075Sobrien * For non-static methods or constructors, this is the type with a leading parameter, 16190075Sobrien * a reference to declaring class. For static methods, it is the same as the declared type. 16290075Sobrien */ 16390075Sobrien public MethodType getInvocationType() { 16490075Sobrien MethodType itype = getMethodOrFieldType(); 16590075Sobrien if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial) 16690075Sobrien return itype.changeReturnType(clazz); 16790075Sobrien if (!isStatic()) 16890075Sobrien return itype.insertParameterTypes(0, clazz); 16990075Sobrien return itype; 17090075Sobrien } 17190075Sobrien 17290075Sobrien /** Utility method producing the parameter types of the method type. */ 17390075Sobrien public Class<?>[] getParameterTypes() { 17490075Sobrien return getMethodType().parameterArray(); 17590075Sobrien } 17690075Sobrien 17790075Sobrien /** Utility method producing the return type of the method type. */ 17890075Sobrien public Class<?> getReturnType() { 17990075Sobrien return getMethodType().returnType(); 18090075Sobrien } 18190075Sobrien 18290075Sobrien /** Return the declared type of this member, which 18390075Sobrien * must be a field or type. 18490075Sobrien * If it is a type member, that type itself is returned. 18590075Sobrien */ 18690075Sobrien public Class<?> getFieldType() { 18790075Sobrien if (type == null) { 18890075Sobrien expandFromVM(); 18996263Sobrien if (type == null) { 19096263Sobrien return null; 19190075Sobrien } 19290075Sobrien } 19390075Sobrien if (isInvocable()) { 19490075Sobrien throw newIllegalArgumentException("not a field or nested class, no simple type"); 19590075Sobrien } 19690075Sobrien 19790075Sobrien { 19890075Sobrien // Get a snapshot of type which doesn't get changed by racing threads. 19990075Sobrien final Object type = this.type; 20090075Sobrien if (type instanceof Class<?>) { 20190075Sobrien return (Class<?>) type; 20290075Sobrien } 20390075Sobrien } 20490075Sobrien 20590075Sobrien // type is not a Class yet. Convert it thread-safely. 20690075Sobrien synchronized (this) { 20790075Sobrien if (type instanceof String) { 20890075Sobrien String sig = (String) type; 20990075Sobrien MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader()); 21090075Sobrien Class<?> res = mtype.returnType(); 21190075Sobrien type = res; 21290075Sobrien } 21390075Sobrien // Make sure type is a Class for racing threads. 21490075Sobrien assert type instanceof Class<?> : "bad field type " + type; 21590075Sobrien } 21690075Sobrien return (Class<?>) type; 21790075Sobrien } 21890075Sobrien 21990075Sobrien /** Utility method to produce either the method type or field type of this member. */ 22090075Sobrien public Object getType() { 22190075Sobrien return (isInvocable() ? getMethodType() : getFieldType()); 22290075Sobrien } 22390075Sobrien 22490075Sobrien /** Utility method to produce the signature of this member, 22590075Sobrien * used within the class file format to describe its type. 22690075Sobrien */ 22790075Sobrien public String getSignature() { 22890075Sobrien if (type == null) { 22990075Sobrien expandFromVM(); 23090075Sobrien if (type == null) { 231117395Skan return null; 23290075Sobrien } 23390075Sobrien } 23490075Sobrien if (isInvocable()) 23590075Sobrien return BytecodeDescriptor.unparse(getMethodType()); 23652284Sobrien else 23718334Speter return BytecodeDescriptor.unparse(getFieldType()); 23818334Speter } 23918334Speter 24018334Speter /** Return the modifier flags of this member. 24118334Speter * @see java.lang.reflect.Modifier 24218334Speter */ 24318334Speter public int getModifiers() { 24418334Speter return (flags & RECOGNIZED_MODIFIERS); 24518334Speter } 24618334Speter 24718334Speter /** Return the reference kind of this member, or zero if none. 24818334Speter */ 24918334Speter public byte getReferenceKind() { 25018334Speter return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK); 25118334Speter } 25218334Speter private boolean referenceKindIsConsistent() { 25318334Speter byte refKind = getReferenceKind(); 25490075Sobrien if (refKind == REF_NONE) return isType(); 25518334Speter if (isField()) { 25618334Speter assert(staticIsConsistent()); 25718334Speter assert(MethodHandleNatives.refKindIsField(refKind)); 25818334Speter } else if (isConstructor()) { 25918334Speter assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial); 26018334Speter } else if (isMethod()) { 26190075Sobrien assert(staticIsConsistent()); 26290075Sobrien assert(MethodHandleNatives.refKindIsMethod(refKind)); 26318334Speter if (clazz.isInterface()) 26418334Speter assert(refKind == REF_invokeInterface || 26518334Speter refKind == REF_invokeStatic || 26618334Speter refKind == REF_invokeSpecial || 26718334Speter refKind == REF_invokeVirtual && isObjectPublicMethod()); 26890075Sobrien } else { 26918334Speter assert(false); 27090075Sobrien } 27190075Sobrien return true; 27218334Speter } 27318334Speter private boolean isObjectPublicMethod() { 27418334Speter if (clazz == Object.class) return true; 27518334Speter MethodType mtype = getMethodType(); 27618334Speter if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0) 27718334Speter return true; 27818334Speter if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0) 27918334Speter return true; 28018334Speter if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class) 28118334Speter return true; 28290075Sobrien return false; 28390075Sobrien } 28490075Sobrien /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) { 28590075Sobrien int refKind = getReferenceKind(); 28690075Sobrien if (refKind == originalRefKind) return true; 28718334Speter switch (originalRefKind) { 28818334Speter case REF_invokeInterface: 28990075Sobrien // Looking up an interface method, can get (e.g.) Object.hashCode 29090075Sobrien assert(refKind == REF_invokeVirtual || 29190075Sobrien refKind == REF_invokeSpecial) : this; 29290075Sobrien return true; 29390075Sobrien case REF_invokeVirtual: 29418334Speter case REF_newInvokeSpecial: 29590075Sobrien // Looked up a virtual, can get (e.g.) final String.hashCode. 29690075Sobrien assert(refKind == REF_invokeSpecial) : this; 29790075Sobrien return true; 29890075Sobrien } 29990075Sobrien assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind); 30090075Sobrien return true; 30190075Sobrien } 30290075Sobrien private boolean staticIsConsistent() { 30318334Speter byte refKind = getReferenceKind(); 30490075Sobrien return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0; 30518334Speter } 30690075Sobrien private boolean vminfoIsConsistent() { 30718334Speter byte refKind = getReferenceKind(); 30818334Speter assert(isResolved()); // else don't call 30918334Speter Object vminfo = MethodHandleNatives.getMemberVMInfo(this); 31018334Speter assert(vminfo instanceof Object[]); 31118334Speter long vmindex = (Long) ((Object[])vminfo)[0]; 31218334Speter Object vmtarget = ((Object[])vminfo)[1]; 31318334Speter if (MethodHandleNatives.refKindIsField(refKind)) { 31418334Speter assert(vmindex >= 0) : vmindex + ":" + this; 31518334Speter assert(vmtarget instanceof Class); 31618334Speter } else { 31718334Speter if (MethodHandleNatives.refKindDoesDispatch(refKind)) 31818334Speter assert(vmindex >= 0) : vmindex + ":" + this; 31918334Speter else 32090075Sobrien assert(vmindex < 0) : vmindex; 32190075Sobrien assert(vmtarget instanceof MemberName) : vmtarget + " in " + this; 32218334Speter } 32318334Speter return true; 32418334Speter } 32518334Speter 32618334Speter private MemberName changeReferenceKind(byte refKind, byte oldKind) { 32718334Speter assert(getReferenceKind() == oldKind); 32818334Speter assert(MethodHandleNatives.refKindIsValid(refKind)); 32918334Speter flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); 33018334Speter// if (isConstructor() && refKind != REF_newInvokeSpecial) 33118334Speter// flags += (IS_METHOD - IS_CONSTRUCTOR); 33218334Speter// else if (refKind == REF_newInvokeSpecial && isMethod()) 33318334Speter// flags += (IS_CONSTRUCTOR - IS_METHOD); 33418334Speter return this; 33518334Speter } 33690075Sobrien 33790075Sobrien private boolean testFlags(int mask, int value) { 33890075Sobrien return (flags & mask) == value; 33990075Sobrien } 34090075Sobrien private boolean testAllFlags(int mask) { 34118334Speter return testFlags(mask, mask); 34250397Sobrien } 34350397Sobrien private boolean testAnyFlags(int mask) { 34418334Speter return !testFlags(mask, 0); 34518334Speter } 34690075Sobrien 34790075Sobrien /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */ 34890075Sobrien public boolean isMethodHandleInvoke() { 34990075Sobrien final int bits = MH_INVOKE_MODS; 35018334Speter final int negs = Modifier.STATIC; 35118334Speter if (testFlags(bits | negs, bits) && 35218334Speter clazz == MethodHandle.class) { 35318334Speter return isMethodHandleInvokeName(name); 35418334Speter } 35518334Speter return false; 35618334Speter } 35718334Speter public static boolean isMethodHandleInvokeName(String name) { 35818334Speter return name.equals("invoke") || name.equals("invokeExact"); 35918334Speter } 36018334Speter private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC; 36118334Speter 36218334Speter /** Utility method to query the modifier flags of this member. */ 36318334Speter public boolean isStatic() { 36418334Speter return Modifier.isStatic(flags); 36518334Speter } 36690075Sobrien /** Utility method to query the modifier flags of this member. */ 36718334Speter public boolean isPublic() { 36818334Speter return Modifier.isPublic(flags); 36918334Speter } 37018334Speter /** Utility method to query the modifier flags of this member. */ 37190075Sobrien public boolean isPrivate() { 37218334Speter return Modifier.isPrivate(flags); 37318334Speter } 37418334Speter /** Utility method to query the modifier flags of this member. */ 37518334Speter public boolean isProtected() { 37618334Speter return Modifier.isProtected(flags); 37718334Speter } 37850397Sobrien /** Utility method to query the modifier flags of this member. */ 37918334Speter public boolean isFinal() { 38018334Speter return Modifier.isFinal(flags); 38118334Speter } 38218334Speter /** Utility method to query whether this member or its defining class is final. */ 38318334Speter public boolean canBeStaticallyBound() { 38418334Speter return Modifier.isFinal(flags | clazz.getModifiers()); 38550397Sobrien } 38650397Sobrien /** Utility method to query the modifier flags of this member. */ 38750397Sobrien public boolean isVolatile() { 38850397Sobrien return Modifier.isVolatile(flags); 38990075Sobrien } 39018334Speter /** Utility method to query the modifier flags of this member. */ 39118334Speter public boolean isAbstract() { 39218334Speter return Modifier.isAbstract(flags); 39318334Speter } 39418334Speter /** Utility method to query the modifier flags of this member. */ 39518334Speter public boolean isNative() { 39618334Speter return Modifier.isNative(flags); 39718334Speter } 39818334Speter // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo 39918334Speter 40018334Speter // unofficial modifier flags, used by HotSpot: 40118334Speter static final int BRIDGE = 0x00000040; 40218334Speter static final int VARARGS = 0x00000080; 40318334Speter static final int SYNTHETIC = 0x00001000; 40418334Speter static final int ANNOTATION= 0x00002000; 40518334Speter static final int ENUM = 0x00004000; 40618334Speter /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 40718334Speter public boolean isBridge() { 40818334Speter return testAllFlags(IS_METHOD | BRIDGE); 40918334Speter } 41018334Speter /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 41118334Speter public boolean isVarargs() { 41218334Speter return testAllFlags(VARARGS) && isInvocable(); 41318334Speter } 41418334Speter /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 41550397Sobrien public boolean isSynthetic() { 41618334Speter return testAllFlags(SYNTHETIC); 41718334Speter } 41850397Sobrien 41950397Sobrien static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular 42050397Sobrien 42150397Sobrien // modifiers exported by the JVM: 42250397Sobrien static final int RECOGNIZED_MODIFIERS = 0xFFFF; 42318334Speter 42418334Speter // private flags, not part of RECOGNIZED_MODIFIERS: 42590075Sobrien static final int 42690075Sobrien IS_METHOD = MN_IS_METHOD, // method (not constructor) 42790075Sobrien IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor 42890075Sobrien IS_FIELD = MN_IS_FIELD, // field 42918334Speter IS_TYPE = MN_IS_TYPE, // nested type 43018334Speter CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected 43118334Speter 43218334Speter static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; 43318334Speter static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; 43418334Speter static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; 43518334Speter static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; 43618334Speter static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES; 43718334Speter 43818334Speter /** Utility method to query whether this member is a method or constructor. */ 43918334Speter public boolean isInvocable() { 44018334Speter return testAnyFlags(IS_INVOCABLE); 44118334Speter } 44218334Speter /** Utility method to query whether this member is a method, constructor, or field. */ 44318334Speter public boolean isFieldOrMethod() { 44418334Speter return testAnyFlags(IS_FIELD_OR_METHOD); 44518334Speter } 44618334Speter /** Query whether this member is a method. */ 44718334Speter public boolean isMethod() { 44818334Speter return testAllFlags(IS_METHOD); 44990075Sobrien } 45018334Speter /** Query whether this member is a constructor. */ 45118334Speter public boolean isConstructor() { 45252284Sobrien return testAllFlags(IS_CONSTRUCTOR); 45352284Sobrien } 45496263Sobrien /** Query whether this member is a field. */ 45518334Speter public boolean isField() { 45652284Sobrien return testAllFlags(IS_FIELD); 45752284Sobrien } 45890075Sobrien /** Query whether this member is a type. */ 45952284Sobrien public boolean isType() { 46090075Sobrien return testAllFlags(IS_TYPE); 46190075Sobrien } 46218334Speter /** Utility method to query whether this member is neither public, private, nor protected. */ 46318334Speter public boolean isPackage() { 46418334Speter return !testAnyFlags(ALL_ACCESS); 46590075Sobrien } 46696263Sobrien /** Query whether this member has a CallerSensitive annotation. */ 46718334Speter public boolean isCallerSensitive() { 46852284Sobrien return testAllFlags(CALLER_SENSITIVE); 46918334Speter } 47018334Speter 47152284Sobrien /** Utility method to query whether this member is accessible from a given lookup class. */ 47290075Sobrien public boolean isAccessibleFrom(Class<?> lookupClass) { 47390075Sobrien return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, 47490075Sobrien lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE); 47550397Sobrien } 47618334Speter 47796263Sobrien /** Initialize a query. It is not resolved. */ 47896263Sobrien private void init(Class<?> defClass, String name, Object type, int flags) { 47996263Sobrien // defining class is allowed to be null (for a naked name/type pair) 48096263Sobrien //name.toString(); // null check 48118334Speter //type.equals(type); // null check 48218334Speter // fill in fields: 48318334Speter this.clazz = defClass; 48418334Speter this.name = name; 48518334Speter this.type = type; 48618334Speter this.flags = flags; 48790075Sobrien assert(testAnyFlags(ALL_KINDS)); 48890075Sobrien assert(this.resolution == null); // nobody should have touched this yet 48990075Sobrien //assert(referenceKindIsConsistent()); // do this after resolution 49090075Sobrien } 49190075Sobrien 49290075Sobrien /** 49390075Sobrien * Calls down to the VM to fill in the fields. This method is 49490075Sobrien * synchronized to avoid racing calls. 49590075Sobrien */ 49690075Sobrien private void expandFromVM() { 49790075Sobrien if (type != null) { 49890075Sobrien return; 49990075Sobrien } 50090075Sobrien if (!isResolved()) { 50190075Sobrien return; 50290075Sobrien } 50390075Sobrien MethodHandleNatives.expand(this); 50490075Sobrien } 50590075Sobrien 50690075Sobrien // Capturing information from the Core Reflection API: 50790075Sobrien private static int flagsMods(int flags, int mods, byte refKind) { 50890075Sobrien assert((flags & RECOGNIZED_MODIFIERS) == 0); 50990075Sobrien assert((mods & ~RECOGNIZED_MODIFIERS) == 0); 51090075Sobrien assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); 51190075Sobrien return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); 51290075Sobrien } 51318334Speter /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ 51490075Sobrien public MemberName(Method m) { 51590075Sobrien this(m, false); 51690075Sobrien } 51790075Sobrien @SuppressWarnings("LeakingThisInConstructor") 51870635Sobrien public MemberName(Method m, boolean wantSpecial) { 51990075Sobrien m.getClass(); // NPE check 52090075Sobrien // fill in vmtarget, vmindex while we have m in hand: 52190075Sobrien MethodHandleNatives.init(this, m); 52290075Sobrien if (clazz == null) { // MHN.init failed 52370635Sobrien if (m.getDeclaringClass() == MethodHandle.class && 52418334Speter isMethodHandleInvokeName(m.getName())) { 52552284Sobrien // The JVM did not reify this signature-polymorphic instance. 52618334Speter // Need a special case here. 52718334Speter // See comments on MethodHandleNatives.linkMethod. 52818334Speter MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); 52918334Speter int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); 53018334Speter init(MethodHandle.class, m.getName(), type, flags); 53118334Speter if (isMethodHandleInvoke()) 53290075Sobrien return; 53350397Sobrien } 53452284Sobrien throw new LinkageError(m.toString()); 53518334Speter } 53690075Sobrien assert(isResolved() && this.clazz != null); 53752284Sobrien this.name = m.getName(); 53818334Speter if (this.type == null) 53918334Speter this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; 54018334Speter if (wantSpecial) { 54118334Speter if (isAbstract()) 54218334Speter throw new AbstractMethodError(this.toString()); 54318334Speter if (getReferenceKind() == REF_invokeVirtual) 54490075Sobrien changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); 54590075Sobrien else if (getReferenceKind() == REF_invokeInterface) 54690075Sobrien // invokeSpecial on a default method 54790075Sobrien changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); 54890075Sobrien } 54990075Sobrien } 55090075Sobrien public MemberName asSpecial() { 55190075Sobrien switch (getReferenceKind()) { 55290075Sobrien case REF_invokeSpecial: return this; 55390075Sobrien case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); 55490075Sobrien case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); 55590075Sobrien case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial); 55690075Sobrien } 55790075Sobrien throw new IllegalArgumentException(this.toString()); 55890075Sobrien } 55990075Sobrien /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind. 56018334Speter * In that case it must already be REF_invokeSpecial. 56118334Speter */ 56218334Speter public MemberName asConstructor() { 56318334Speter switch (getReferenceKind()) { 56418334Speter case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial); 56518334Speter case REF_newInvokeSpecial: return this; 56690075Sobrien } 56750397Sobrien throw new IllegalArgumentException(this.toString()); 56852284Sobrien } 56918334Speter /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind 57018334Speter * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface. 57190075Sobrien * The end result is to get a fully virtualized version of the MN. 57252284Sobrien * (Note that resolving in the JVM will sometimes devirtualize, changing 57318334Speter * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface 57418334Speter * in some corner cases to either of the previous two; this transform 57518334Speter * undoes that change under the assumption that it occurred.) 57618334Speter */ 57718334Speter public MemberName asNormalOriginal() { 57818334Speter byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual; 57918334Speter byte refKind = getReferenceKind(); 58018334Speter byte newRefKind = refKind; 58118334Speter MemberName result = this; 58218334Speter switch (refKind) { 58318334Speter case REF_invokeInterface: 58418334Speter case REF_invokeVirtual: 58518334Speter case REF_invokeSpecial: 58618334Speter newRefKind = normalVirtual; 58718334Speter break; 58890075Sobrien } 58990075Sobrien if (newRefKind == refKind) 59090075Sobrien return this; 59190075Sobrien result = clone().changeReferenceKind(newRefKind, refKind); 59290075Sobrien assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); 59390075Sobrien return result; 59490075Sobrien } 59590075Sobrien /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ 59690075Sobrien @SuppressWarnings("LeakingThisInConstructor") 59718334Speter public MemberName(Constructor<?> ctor) { 59818334Speter ctor.getClass(); // NPE check 59918334Speter // fill in vmtarget, vmindex while we have ctor in hand: 60018334Speter MethodHandleNatives.init(this, ctor); 60118334Speter assert(isResolved() && this.clazz != null); 60218334Speter this.name = CONSTRUCTOR_NAME; 60318334Speter if (this.type == null) 60418334Speter this.type = new Object[] { void.class, ctor.getParameterTypes() }; 60518334Speter } 60618334Speter /** Create a name for the given reflected field. The resulting name will be in a resolved state. 60718334Speter */ 60818334Speter public MemberName(Field fld) { 60918334Speter this(fld, false); 61018334Speter } 61118334Speter @SuppressWarnings("LeakingThisInConstructor") 61218334Speter public MemberName(Field fld, boolean makeSetter) { 61390075Sobrien fld.getClass(); // NPE check 61490075Sobrien // fill in vmtarget, vmindex while we have fld in hand: 61518334Speter MethodHandleNatives.init(this, fld); 61690075Sobrien assert(isResolved() && this.clazz != null); 61790075Sobrien this.name = fld.getName(); 61890075Sobrien this.type = fld.getType(); 61990075Sobrien assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 62090075Sobrien byte refKind = this.getReferenceKind(); 621117395Skan assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); 622117395Skan if (makeSetter) { 62390075Sobrien changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); 62490075Sobrien } 62590075Sobrien } 62690075Sobrien public boolean isGetter() { 62790075Sobrien return MethodHandleNatives.refKindIsGetter(getReferenceKind()); 62890075Sobrien } 62990075Sobrien public boolean isSetter() { 63090075Sobrien return MethodHandleNatives.refKindIsSetter(getReferenceKind()); 63190075Sobrien } 63290075Sobrien public MemberName asSetter() { 63390075Sobrien byte refKind = getReferenceKind(); 63490075Sobrien assert(MethodHandleNatives.refKindIsGetter(refKind)); 63590075Sobrien assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 63690075Sobrien byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); 63790075Sobrien return clone().changeReferenceKind(setterRefKind, refKind); 63890075Sobrien } 63990075Sobrien /** Create a name for the given class. The resulting name will be in a resolved state. */ 64018334Speter public MemberName(Class<?> type) { 64118334Speter init(type.getDeclaringClass(), type.getSimpleName(), type, 64218334Speter flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); 64318334Speter initResolved(true); 64452284Sobrien } 64518334Speter 64618334Speter /** 64750397Sobrien * Create a name for a signature-polymorphic invoker. 64850397Sobrien * This is a placeholder for a signature-polymorphic instance 64950397Sobrien * (of MH.invokeExact, etc.) that the JVM does not reify. 65050397Sobrien * See comments on {@link MethodHandleNatives#linkMethod}. 65152284Sobrien */ 65252284Sobrien static MemberName makeMethodHandleInvoke(String name, MethodType type) { 65390075Sobrien return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC); 65418334Speter } 65518334Speter static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) { 65690075Sobrien MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual); 65718334Speter mem.flags |= mods; // it's not resolved, but add these modifiers anyway 65890075Sobrien assert(mem.isMethodHandleInvoke()) : mem; 65990075Sobrien return mem; 66090075Sobrien } 66190075Sobrien 66290075Sobrien // bare-bones constructor; the JVM will fill it in 66390075Sobrien MemberName() { } 66490075Sobrien 66590075Sobrien // locally useful cloner 66690075Sobrien @Override protected MemberName clone() { 66790075Sobrien try { 66890075Sobrien return (MemberName) super.clone(); 66990075Sobrien } catch (CloneNotSupportedException ex) { 67090075Sobrien throw newInternalError(ex); 67190075Sobrien } 67290075Sobrien } 67390075Sobrien 67490075Sobrien /** Get the definition of this member name. 67590075Sobrien * This may be in a super-class of the declaring class of this member. 67618334Speter */ 67790075Sobrien public MemberName getDefinition() { 67890075Sobrien if (!isResolved()) throw new IllegalStateException("must be resolved: "+this); 67990075Sobrien if (isType()) return this; 68090075Sobrien MemberName res = this.clone(); 68190075Sobrien res.clazz = null; 68290075Sobrien res.type = null; 68390075Sobrien res.name = null; 68490075Sobrien res.resolution = res; 68590075Sobrien res.expandFromVM(); 68690075Sobrien assert(res.getName().equals(this.getName())); 68790075Sobrien return res; 68890075Sobrien } 68990075Sobrien 69018334Speter @Override 69118334Speter public int hashCode() { 69252284Sobrien return Objects.hash(clazz, getReferenceKind(), name, getType()); 69352284Sobrien } 69452284Sobrien @Override 69552284Sobrien public boolean equals(Object that) { 69652284Sobrien return (that instanceof MemberName && this.equals((MemberName)that)); 69752284Sobrien } 69890075Sobrien 69952284Sobrien /** Decide if two member names have exactly the same symbolic content. 70090075Sobrien * Does not take into account any actual class members, so even if 70152284Sobrien * two member names resolve to the same actual member, they may 70252284Sobrien * be distinct references. 70352284Sobrien */ 70452284Sobrien public boolean equals(MemberName that) { 70552284Sobrien if (this == that) return true; 70690075Sobrien if (that == null) return false; 70790075Sobrien return this.clazz == that.clazz 70852284Sobrien && this.getReferenceKind() == that.getReferenceKind() 70990075Sobrien && Objects.equals(this.name, that.name) 71052284Sobrien && Objects.equals(this.getType(), that.getType()); 71190075Sobrien } 71290075Sobrien 71390075Sobrien // Construction from symbolic parts, for queries: 71452284Sobrien /** Create a field or type name from the given components: 71552284Sobrien * Declaring class, name, type, reference kind. 71652284Sobrien * The declaring class may be supplied as null if this is to be a bare name and type. 71752284Sobrien * The resulting name will in an unresolved state. 71852284Sobrien */ 71990075Sobrien public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { 72090075Sobrien init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); 72152284Sobrien initResolved(false); 72252284Sobrien } 72352284Sobrien /** Create a field or type name from the given components: Declaring class, name, type. 72452284Sobrien * The declaring class may be supplied as null if this is to be a bare name and type. 72590075Sobrien * The modifier flags default to zero. 72690075Sobrien * The resulting name will in an unresolved state. 72790075Sobrien */ 72890075Sobrien public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) { 72990075Sobrien this(defClass, name, type, REF_NONE); 73090075Sobrien initResolved(false); 73190075Sobrien } 73252284Sobrien /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. 73352284Sobrien * It will be a constructor if and only if the name is {@code "<init>"}. 73452284Sobrien * The declaring class may be supplied as null if this is to be a bare name and type. 73552284Sobrien * The last argument is optional, a boolean which requests REF_invokeSpecial. 73652284Sobrien * The resulting name will in an unresolved state. 73752284Sobrien */ 73852284Sobrien public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { 73952284Sobrien int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); 74052284Sobrien init(defClass, name, type, flagsMods(initFlags, 0, refKind)); 74152284Sobrien initResolved(false); 74252284Sobrien } 74352284Sobrien /** Create a method, constructor, or field name from the given components: 74452284Sobrien * Reference kind, declaring class, name, type. 74552284Sobrien */ 74690075Sobrien public MemberName(byte refKind, Class<?> defClass, String name, Object type) { 74790075Sobrien int kindFlags; 74890075Sobrien if (MethodHandleNatives.refKindIsField(refKind)) { 74990075Sobrien kindFlags = IS_FIELD; 75090075Sobrien if (!(type instanceof Class)) 75190075Sobrien throw newIllegalArgumentException("not a field type"); 75290075Sobrien } else if (MethodHandleNatives.refKindIsMethod(refKind)) { 75390075Sobrien kindFlags = IS_METHOD; 75490075Sobrien if (!(type instanceof MethodType)) 75552284Sobrien throw newIllegalArgumentException("not a method type"); 75652284Sobrien } else if (refKind == REF_newInvokeSpecial) { 75790075Sobrien kindFlags = IS_CONSTRUCTOR; 75852284Sobrien if (!(type instanceof MethodType) || 75952284Sobrien !CONSTRUCTOR_NAME.equals(name)) 76052284Sobrien throw newIllegalArgumentException("not a constructor type or name"); 76152284Sobrien } else { 76252284Sobrien throw newIllegalArgumentException("bad reference kind "+refKind); 76390075Sobrien } 76452284Sobrien init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); 76552284Sobrien initResolved(false); 76652284Sobrien } 76790075Sobrien /** Query whether this member name is resolved to a non-static, non-final method. 76890075Sobrien */ 76990075Sobrien public boolean hasReceiverTypeDispatch() { 77090075Sobrien return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); 77190075Sobrien } 77290075Sobrien 77390075Sobrien /** Query whether this member name is resolved. 77490075Sobrien * A resolved member name is one for which the JVM has found 77590075Sobrien * a method, constructor, field, or type binding corresponding exactly to the name. 77690075Sobrien * (Document?) 77790075Sobrien */ 77890075Sobrien public boolean isResolved() { 77990075Sobrien return resolution == null; 78090075Sobrien } 78190075Sobrien 78290075Sobrien private void initResolved(boolean isResolved) { 78390075Sobrien assert(this.resolution == null); // not initialized yet! 78490075Sobrien if (!isResolved) 78590075Sobrien this.resolution = this; 78690075Sobrien assert(isResolved() == isResolved); 78790075Sobrien } 78890075Sobrien 78990075Sobrien void checkForTypeAlias() { 79090075Sobrien if (isInvocable()) { 79190075Sobrien MethodType type; 79290075Sobrien if (this.type instanceof MethodType) 79390075Sobrien type = (MethodType) this.type; 79490075Sobrien else 79552284Sobrien this.type = type = getMethodType(); 79690075Sobrien if (type.erase() == type) return; 79752284Sobrien if (VerifyAccess.isTypeVisible(type, clazz)) return; 79852284Sobrien throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); 79990075Sobrien } else { 80090075Sobrien Class<?> type; 80190075Sobrien if (this.type instanceof Class<?>) 80290075Sobrien type = (Class<?>) this.type; 80390075Sobrien else 80490075Sobrien this.type = type = getFieldType(); 80590075Sobrien if (VerifyAccess.isTypeVisible(type, clazz)) return; 80690075Sobrien throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); 80790075Sobrien } 808117395Skan } 809117395Skan 810117395Skan 811117395Skan /** Produce a string form of this member name. 812117395Skan * For types, it is simply the type's own string (as reported by {@code toString}). 813117395Skan * For fields, it is {@code "DeclaringClass.name/type"}. 814117395Skan * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}. 815117395Skan * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted. 816117395Skan * If the member is unresolved, a prefix {@code "*."} is prepended. 817117395Skan */ 818117395Skan @SuppressWarnings("LocalVariableHidesMemberVariable") 819117395Skan @Override 820117395Skan public String toString() { 821117395Skan if (isType()) 822117395Skan return type.toString(); // class java.lang.String 82390075Sobrien // else it is a field, method, or constructor 82490075Sobrien StringBuilder buf = new StringBuilder(); 82590075Sobrien if (getDeclaringClass() != null) { 82690075Sobrien buf.append(getName(clazz)); 82790075Sobrien buf.append('.'); 82890075Sobrien } 82990075Sobrien String name = getName(); 83090075Sobrien buf.append(name == null ? "*" : name); 83190075Sobrien Object type = getType(); 83290075Sobrien if (!isInvocable()) { 83390075Sobrien buf.append('/'); 83490075Sobrien buf.append(type == null ? "*" : getName(type)); 83590075Sobrien } else { 83690075Sobrien buf.append(type == null ? "(*)*" : getName(type)); 83790075Sobrien } 83890075Sobrien byte refKind = getReferenceKind(); 83990075Sobrien if (refKind != REF_NONE) { 84090075Sobrien buf.append('/'); 84190075Sobrien buf.append(MethodHandleNatives.refKindName(refKind)); 84290075Sobrien } 84390075Sobrien //buf.append("#").append(System.identityHashCode(this)); 84490075Sobrien return buf.toString(); 84590075Sobrien } 846119256Skan private static String getName(Object obj) { 847119256Skan if (obj instanceof Class<?>) 848119256Skan return ((Class<?>)obj).getName(); 84990075Sobrien return String.valueOf(obj); 85090075Sobrien } 85190075Sobrien 852119256Skan public IllegalAccessException makeAccessException(String message, Object from) { 85390075Sobrien message = message + ": "+ toString(); 85490075Sobrien if (from != null) message += ", from " + from; 85590075Sobrien return new IllegalAccessException(message); 85690075Sobrien } 85790075Sobrien private String message() { 85890075Sobrien if (isResolved()) 85990075Sobrien return "no access"; 86090075Sobrien else if (isConstructor()) 86190075Sobrien return "no such constructor"; 86290075Sobrien else if (isMethod()) 86390075Sobrien return "no such method"; 86490075Sobrien else 86590075Sobrien return "no such field"; 86690075Sobrien } 86790075Sobrien public ReflectiveOperationException makeAccessException() { 86852284Sobrien String message = message() + ": "+ toString(); 86952284Sobrien ReflectiveOperationException ex; 87052284Sobrien if (isResolved() || !(resolution instanceof NoSuchMethodError || 87152284Sobrien resolution instanceof NoSuchFieldError)) 87252284Sobrien ex = new IllegalAccessException(message); 87352284Sobrien else if (isConstructor()) 87452284Sobrien ex = new NoSuchMethodException(message); 87552284Sobrien else if (isMethod()) 87652284Sobrien ex = new NoSuchMethodException(message); 87752284Sobrien else 87852284Sobrien ex = new NoSuchFieldException(message); 87952284Sobrien if (resolution instanceof Throwable) 88052284Sobrien ex.initCause((Throwable) resolution); 88152284Sobrien return ex; 88252284Sobrien } 88352284Sobrien 88452284Sobrien /** Actually making a query requires an access check. */ 88552284Sobrien /*non-public*/ static Factory getFactory() { 88652284Sobrien return Factory.INSTANCE; 88752284Sobrien } 88852284Sobrien /** A factory type for resolving member names with the help of the VM. 88952284Sobrien * TBD: Define access-safe public constructors for this factory. 89052284Sobrien */ 89152284Sobrien /*non-public*/ static class Factory { 89252284Sobrien private Factory() { } // singleton pattern 89352284Sobrien static Factory INSTANCE = new Factory(); 89452284Sobrien 89552284Sobrien private static int ALLOWED_FLAGS = ALL_KINDS; 89652284Sobrien 89752284Sobrien /// Queries 89852284Sobrien List<MemberName> getMembers(Class<?> defc, 89952284Sobrien String matchName, Object matchType, 90052284Sobrien int matchFlags, Class<?> lookupClass) { 90152284Sobrien matchFlags &= ALLOWED_FLAGS; 90252284Sobrien String matchSig = null; 903117395Skan if (matchType != null) { 904117395Skan matchSig = BytecodeDescriptor.unparse(matchType); 905117395Skan if (matchSig.startsWith("(")) 906117395Skan matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); 907117395Skan else 908117395Skan matchFlags &= ~(ALL_KINDS & ~IS_FIELD); 90952284Sobrien } 91052284Sobrien final int BUF_MAX = 0x2000; 91152284Sobrien int len1 = matchName == null ? 10 : matchType == null ? 4 : 1; 91252284Sobrien MemberName[] buf = newMemberBuffer(len1); 91352284Sobrien int totalCount = 0; 91452284Sobrien ArrayList<MemberName[]> bufs = null; 91552284Sobrien int bufCount = 0; 91652284Sobrien for (;;) { 91752284Sobrien bufCount = MethodHandleNatives.getMembers(defc, 91890075Sobrien matchName, matchSig, matchFlags, 91952284Sobrien lookupClass, 92052284Sobrien totalCount, buf); 92152284Sobrien if (bufCount <= buf.length) { 92252284Sobrien if (bufCount < 0) bufCount = 0; 92352284Sobrien totalCount += bufCount; 92452284Sobrien break; 92552284Sobrien } 92652284Sobrien // JVM returned to us with an intentional overflow! 92752284Sobrien totalCount += buf.length; 92852284Sobrien int excess = bufCount - buf.length; 92952284Sobrien if (bufs == null) bufs = new ArrayList<>(1); 93090075Sobrien bufs.add(buf); 93152284Sobrien int len2 = buf.length; 93252284Sobrien len2 = Math.max(len2, excess); 93352284Sobrien len2 = Math.max(len2, totalCount / 4); 93452284Sobrien buf = newMemberBuffer(Math.min(BUF_MAX, len2)); 93552284Sobrien } 93652284Sobrien ArrayList<MemberName> result = new ArrayList<>(totalCount); 93790075Sobrien if (bufs != null) { 93852284Sobrien for (MemberName[] buf0 : bufs) { 93952284Sobrien Collections.addAll(result, buf0); 94052284Sobrien } 94152284Sobrien } 94290075Sobrien result.addAll(Arrays.asList(buf).subList(0, bufCount)); 94352284Sobrien // Signature matching is not the same as type matching, since 94452284Sobrien // one signature might correspond to several types. 94552284Sobrien // So if matchType is a Class or MethodType, refilter the results. 94652284Sobrien if (matchType != null && matchType != matchSig) { 94752284Sobrien for (Iterator<MemberName> it = result.iterator(); it.hasNext();) { 94852284Sobrien MemberName m = it.next(); 94952284Sobrien if (!matchType.equals(m.getType())) 95052284Sobrien it.remove(); 95152284Sobrien } 95252284Sobrien } 95352284Sobrien return result; 95452284Sobrien } 95552284Sobrien /** Produce a resolved version of the given member. 95652284Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 95752284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 95852284Sobrien * If lookup fails or access is not permitted, null is returned. 95952284Sobrien * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 96052284Sobrien */ 96152284Sobrien private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { 96252284Sobrien MemberName m = ref.clone(); // JVM will side-effect the ref 96352284Sobrien assert(refKind == m.getReferenceKind()); 96452284Sobrien try { 96552284Sobrien m = MethodHandleNatives.resolve(m, lookupClass); 96652284Sobrien m.checkForTypeAlias(); 96752284Sobrien m.resolution = null; 96852284Sobrien } catch (LinkageError ex) { 96952284Sobrien // JVM reports that the "bytecode behavior" would get an error 97052284Sobrien assert(!m.isResolved()); 97152284Sobrien m.resolution = ex; 97252284Sobrien return m; 97352284Sobrien } 97452284Sobrien assert(m.referenceKindIsConsistent()); 97552284Sobrien m.initResolved(true); 97652284Sobrien assert(m.vminfoIsConsistent()); 97752284Sobrien return m; 97852284Sobrien } 97952284Sobrien /** Produce a resolved version of the given member. 98090075Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 98152284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 98252284Sobrien * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown. 98352284Sobrien * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 98490075Sobrien */ 98590075Sobrien public 98690075Sobrien <NoSuchMemberException extends ReflectiveOperationException> 98790075Sobrien MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, 98890075Sobrien Class<NoSuchMemberException> nsmClass) 98952284Sobrien throws IllegalAccessException, NoSuchMemberException { 99052284Sobrien MemberName result = resolve(refKind, m, lookupClass); 99152284Sobrien if (result.isResolved()) 99252284Sobrien return result; 99352284Sobrien ReflectiveOperationException ex = result.makeAccessException(); 99452284Sobrien if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex; 99590075Sobrien throw nsmClass.cast(ex); 99690075Sobrien } 99752284Sobrien /** Produce a resolved version of the given member. 99852284Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 99952284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 1000117395Skan * If lookup fails or access is not permitted, return null. 1001117395Skan * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 100252284Sobrien */ 100352284Sobrien public 100452284Sobrien MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { 100552284Sobrien MemberName result = resolve(refKind, m, lookupClass); 100652284Sobrien if (result.isResolved()) 100752284Sobrien return result; 100852284Sobrien return null; 100990075Sobrien } 101052284Sobrien /** Return a list of all methods defined by the given class. 101152284Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 101252284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 101352284Sobrien * Inaccessible members are not added to the last. 101452284Sobrien */ 101552284Sobrien public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 101652284Sobrien Class<?> lookupClass) { 101752284Sobrien return getMethods(defc, searchSupers, null, null, lookupClass); 101852284Sobrien } 101952284Sobrien /** Return a list of matching methods defined by the given class. 102052284Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 102152284Sobrien * Returned methods will match the name (if not null) and the type (if not null). 102252284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 102352284Sobrien * Inaccessible members are not added to the last. 102452284Sobrien */ 102552284Sobrien public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 102652284Sobrien String name, MethodType type, Class<?> lookupClass) { 102752284Sobrien int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 102852284Sobrien return getMembers(defc, name, type, matchFlags, lookupClass); 102952284Sobrien } 103052284Sobrien /** Return a list of all constructors defined by the given class. 103152284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 103252284Sobrien * Inaccessible members are not added to the last. 103352284Sobrien */ 103452284Sobrien public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) { 103552284Sobrien return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); 103652284Sobrien } 103752284Sobrien /** Return a list of all fields defined by the given class. 1038117395Skan * Super types are searched (for inherited members) if {@code searchSupers} is true. 1039117395Skan * Access checking is performed on behalf of the given {@code lookupClass}. 1040117395Skan * Inaccessible members are not added to the last. 104152284Sobrien */ 104290075Sobrien public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 104390075Sobrien Class<?> lookupClass) { 104452284Sobrien return getFields(defc, searchSupers, null, null, lookupClass); 104552284Sobrien } 104652284Sobrien /** Return a list of all fields defined by the given class. 104790075Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 104852284Sobrien * Returned fields will match the name (if not null) and the type (if not null). 104952284Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 105052284Sobrien * Inaccessible members are not added to the last. 105152284Sobrien */ 105252284Sobrien public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 105352284Sobrien String name, Class<?> type, Class<?> lookupClass) { 105452284Sobrien int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 105552284Sobrien return getMembers(defc, name, type, matchFlags, lookupClass); 105652284Sobrien } 105752284Sobrien /** Return a list of all nested types defined by the given class. 105852284Sobrien * Super types are searched (for inherited members) if {@code searchSupers} is true. 105990075Sobrien * Access checking is performed on behalf of the given {@code lookupClass}. 106052284Sobrien * Inaccessible members are not added to the last. 106152284Sobrien */ 106252284Sobrien public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers, 106352284Sobrien Class<?> lookupClass) { 106452284Sobrien int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); 106552284Sobrien return getMembers(defc, null, null, matchFlags, lookupClass); 106652284Sobrien } 106752284Sobrien private static MemberName[] newMemberBuffer(int length) { 106852284Sobrien MemberName[] buf = new MemberName[length]; 106952284Sobrien // fill the buffer with dummy structs for the JVM to fill in 107052284Sobrien for (int i = 0; i < length; i++) 107152284Sobrien buf[i] = new MemberName(); 107252284Sobrien return buf; 107352284Sobrien } 107452284Sobrien } 107552284Sobrien 107652284Sobrien// static { 107752284Sobrien// System.out.println("Hello world! My methods are:"); 107852284Sobrien// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null)); 107952284Sobrien// } 108090075Sobrien} 108190075Sobrien