1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MemberName.java Sat Aug 09 11:11:13 2014 +0200
1.3 @@ -0,0 +1,1080 @@
1.4 +/*
1.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.lang.invoke;
1.30 +
1.31 +import sun.invoke.util.BytecodeDescriptor;
1.32 +import sun.invoke.util.VerifyAccess;
1.33 +
1.34 +import java.lang.reflect.Constructor;
1.35 +import java.lang.reflect.Field;
1.36 +import java.lang.reflect.Method;
1.37 +import java.lang.reflect.Member;
1.38 +import java.lang.reflect.Modifier;
1.39 +import java.util.ArrayList;
1.40 +import java.util.Arrays;
1.41 +import java.util.Collections;
1.42 +import java.util.Iterator;
1.43 +import java.util.List;
1.44 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
1.45 +import static java.lang.invoke.MethodHandleStatics.*;
1.46 +import java.util.Objects;
1.47 +
1.48 +/**
1.49 + * A {@code MemberName} is a compact symbolic datum which fully characterizes
1.50 + * a method or field reference.
1.51 + * A member name refers to a field, method, constructor, or member type.
1.52 + * Every member name has a simple name (a string) and a type (either a Class or MethodType).
1.53 + * A member name may also have a non-null declaring class, or it may be simply
1.54 + * a naked name/type pair.
1.55 + * A member name may also have non-zero modifier flags.
1.56 + * Finally, a member name may be either resolved or unresolved.
1.57 + * If it is resolved, the existence of the named
1.58 + * <p>
1.59 + * Whether resolved or not, a member name provides no access rights or
1.60 + * invocation capability to its possessor. It is merely a compact
1.61 + * representation of all symbolic information necessary to link to
1.62 + * and properly use the named member.
1.63 + * <p>
1.64 + * When resolved, a member name's internal implementation may include references to JVM metadata.
1.65 + * This representation is stateless and only decriptive.
1.66 + * It provides no private information and no capability to use the member.
1.67 + * <p>
1.68 + * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
1.69 + * about the internals of a method (except its bytecodes) and also
1.70 + * allows invocation. A MemberName is much lighter than a Method,
1.71 + * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
1.72 + * and those seven fields omit much of the information in Method.
1.73 + * @author jrose
1.74 + */
1.75 +/*non-public*/ final class MemberName implements Member, Cloneable {
1.76 + private Class<?> clazz; // class in which the method is defined
1.77 + private String name; // may be null if not yet materialized
1.78 + private Object type; // may be null if not yet materialized
1.79 + private int flags; // modifier bits; see reflect.Modifier
1.80 + //@Injected JVM_Method* vmtarget;
1.81 + //@Injected int vmindex;
1.82 + private Object resolution; // if null, this guy is resolved
1.83 +
1.84 + /** Return the declaring class of this member.
1.85 + * In the case of a bare name and type, the declaring class will be null.
1.86 + */
1.87 + public Class<?> getDeclaringClass() {
1.88 + return clazz;
1.89 + }
1.90 +
1.91 + /** Utility method producing the class loader of the declaring class. */
1.92 + public ClassLoader getClassLoader() {
1.93 + return clazz.getClassLoader();
1.94 + }
1.95 +
1.96 + /** Return the simple name of this member.
1.97 + * For a type, it is the same as {@link Class#getSimpleName}.
1.98 + * For a method or field, it is the simple name of the member.
1.99 + * For a constructor, it is always {@code "<init>"}.
1.100 + */
1.101 + public String getName() {
1.102 + if (name == null) {
1.103 + expandFromVM();
1.104 + if (name == null) {
1.105 + return null;
1.106 + }
1.107 + }
1.108 + return name;
1.109 + }
1.110 +
1.111 + public MethodType getMethodOrFieldType() {
1.112 + if (isInvocable())
1.113 + return getMethodType();
1.114 + if (isGetter())
1.115 + return MethodType.methodType(getFieldType());
1.116 + if (isSetter())
1.117 + return MethodType.methodType(void.class, getFieldType());
1.118 + throw new InternalError("not a method or field: "+this);
1.119 + }
1.120 +
1.121 + /** Return the declared type of this member, which
1.122 + * must be a method or constructor.
1.123 + */
1.124 + public MethodType getMethodType() {
1.125 + if (type == null) {
1.126 + expandFromVM();
1.127 + if (type == null) {
1.128 + return null;
1.129 + }
1.130 + }
1.131 + if (!isInvocable()) {
1.132 + throw newIllegalArgumentException("not invocable, no method type");
1.133 + }
1.134 +
1.135 + {
1.136 + // Get a snapshot of type which doesn't get changed by racing threads.
1.137 + final Object type = this.type;
1.138 + if (type instanceof MethodType) {
1.139 + return (MethodType) type;
1.140 + }
1.141 + }
1.142 +
1.143 + // type is not a MethodType yet. Convert it thread-safely.
1.144 + synchronized (this) {
1.145 + if (type instanceof String) {
1.146 + String sig = (String) type;
1.147 + MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
1.148 + type = res;
1.149 + } else if (type instanceof Object[]) {
1.150 + Object[] typeInfo = (Object[]) type;
1.151 + Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
1.152 + Class<?> rtype = (Class<?>) typeInfo[0];
1.153 + MethodType res = MethodType.methodType(rtype, ptypes);
1.154 + type = res;
1.155 + }
1.156 + // Make sure type is a MethodType for racing threads.
1.157 + assert type instanceof MethodType : "bad method type " + type;
1.158 + }
1.159 + return (MethodType) type;
1.160 + }
1.161 +
1.162 + /** Return the actual type under which this method or constructor must be invoked.
1.163 + * For non-static methods or constructors, this is the type with a leading parameter,
1.164 + * a reference to declaring class. For static methods, it is the same as the declared type.
1.165 + */
1.166 + public MethodType getInvocationType() {
1.167 + MethodType itype = getMethodOrFieldType();
1.168 + if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
1.169 + return itype.changeReturnType(clazz);
1.170 + if (!isStatic())
1.171 + return itype.insertParameterTypes(0, clazz);
1.172 + return itype;
1.173 + }
1.174 +
1.175 + /** Utility method producing the parameter types of the method type. */
1.176 + public Class<?>[] getParameterTypes() {
1.177 + return getMethodType().parameterArray();
1.178 + }
1.179 +
1.180 + /** Utility method producing the return type of the method type. */
1.181 + public Class<?> getReturnType() {
1.182 + return getMethodType().returnType();
1.183 + }
1.184 +
1.185 + /** Return the declared type of this member, which
1.186 + * must be a field or type.
1.187 + * If it is a type member, that type itself is returned.
1.188 + */
1.189 + public Class<?> getFieldType() {
1.190 + if (type == null) {
1.191 + expandFromVM();
1.192 + if (type == null) {
1.193 + return null;
1.194 + }
1.195 + }
1.196 + if (isInvocable()) {
1.197 + throw newIllegalArgumentException("not a field or nested class, no simple type");
1.198 + }
1.199 +
1.200 + {
1.201 + // Get a snapshot of type which doesn't get changed by racing threads.
1.202 + final Object type = this.type;
1.203 + if (type instanceof Class<?>) {
1.204 + return (Class<?>) type;
1.205 + }
1.206 + }
1.207 +
1.208 + // type is not a Class yet. Convert it thread-safely.
1.209 + synchronized (this) {
1.210 + if (type instanceof String) {
1.211 + String sig = (String) type;
1.212 + MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
1.213 + Class<?> res = mtype.returnType();
1.214 + type = res;
1.215 + }
1.216 + // Make sure type is a Class for racing threads.
1.217 + assert type instanceof Class<?> : "bad field type " + type;
1.218 + }
1.219 + return (Class<?>) type;
1.220 + }
1.221 +
1.222 + /** Utility method to produce either the method type or field type of this member. */
1.223 + public Object getType() {
1.224 + return (isInvocable() ? getMethodType() : getFieldType());
1.225 + }
1.226 +
1.227 + /** Utility method to produce the signature of this member,
1.228 + * used within the class file format to describe its type.
1.229 + */
1.230 + public String getSignature() {
1.231 + if (type == null) {
1.232 + expandFromVM();
1.233 + if (type == null) {
1.234 + return null;
1.235 + }
1.236 + }
1.237 + if (isInvocable())
1.238 + return BytecodeDescriptor.unparse(getMethodType());
1.239 + else
1.240 + return BytecodeDescriptor.unparse(getFieldType());
1.241 + }
1.242 +
1.243 + /** Return the modifier flags of this member.
1.244 + * @see java.lang.reflect.Modifier
1.245 + */
1.246 + public int getModifiers() {
1.247 + return (flags & RECOGNIZED_MODIFIERS);
1.248 + }
1.249 +
1.250 + /** Return the reference kind of this member, or zero if none.
1.251 + */
1.252 + public byte getReferenceKind() {
1.253 + return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
1.254 + }
1.255 + private boolean referenceKindIsConsistent() {
1.256 + byte refKind = getReferenceKind();
1.257 + if (refKind == REF_NONE) return isType();
1.258 + if (isField()) {
1.259 + assert(staticIsConsistent());
1.260 + assert(MethodHandleNatives.refKindIsField(refKind));
1.261 + } else if (isConstructor()) {
1.262 + assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
1.263 + } else if (isMethod()) {
1.264 + assert(staticIsConsistent());
1.265 + assert(MethodHandleNatives.refKindIsMethod(refKind));
1.266 + if (clazz.isInterface())
1.267 + assert(refKind == REF_invokeInterface ||
1.268 + refKind == REF_invokeStatic ||
1.269 + refKind == REF_invokeSpecial ||
1.270 + refKind == REF_invokeVirtual && isObjectPublicMethod());
1.271 + } else {
1.272 + assert(false);
1.273 + }
1.274 + return true;
1.275 + }
1.276 + private boolean isObjectPublicMethod() {
1.277 + if (clazz == Object.class) return true;
1.278 + MethodType mtype = getMethodType();
1.279 + if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
1.280 + return true;
1.281 + if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
1.282 + return true;
1.283 + if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
1.284 + return true;
1.285 + return false;
1.286 + }
1.287 + /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) {
1.288 + int refKind = getReferenceKind();
1.289 + if (refKind == originalRefKind) return true;
1.290 + switch (originalRefKind) {
1.291 + case REF_invokeInterface:
1.292 + // Looking up an interface method, can get (e.g.) Object.hashCode
1.293 + assert(refKind == REF_invokeVirtual ||
1.294 + refKind == REF_invokeSpecial) : this;
1.295 + return true;
1.296 + case REF_invokeVirtual:
1.297 + case REF_newInvokeSpecial:
1.298 + // Looked up a virtual, can get (e.g.) final String.hashCode.
1.299 + assert(refKind == REF_invokeSpecial) : this;
1.300 + return true;
1.301 + }
1.302 + assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
1.303 + return true;
1.304 + }
1.305 + private boolean staticIsConsistent() {
1.306 + byte refKind = getReferenceKind();
1.307 + return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
1.308 + }
1.309 + private boolean vminfoIsConsistent() {
1.310 + byte refKind = getReferenceKind();
1.311 + assert(isResolved()); // else don't call
1.312 + Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
1.313 + assert(vminfo instanceof Object[]);
1.314 + long vmindex = (Long) ((Object[])vminfo)[0];
1.315 + Object vmtarget = ((Object[])vminfo)[1];
1.316 + if (MethodHandleNatives.refKindIsField(refKind)) {
1.317 + assert(vmindex >= 0) : vmindex + ":" + this;
1.318 + assert(vmtarget instanceof Class);
1.319 + } else {
1.320 + if (MethodHandleNatives.refKindDoesDispatch(refKind))
1.321 + assert(vmindex >= 0) : vmindex + ":" + this;
1.322 + else
1.323 + assert(vmindex < 0) : vmindex;
1.324 + assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
1.325 + }
1.326 + return true;
1.327 + }
1.328 +
1.329 + private MemberName changeReferenceKind(byte refKind, byte oldKind) {
1.330 + assert(getReferenceKind() == oldKind);
1.331 + assert(MethodHandleNatives.refKindIsValid(refKind));
1.332 + flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
1.333 +// if (isConstructor() && refKind != REF_newInvokeSpecial)
1.334 +// flags += (IS_METHOD - IS_CONSTRUCTOR);
1.335 +// else if (refKind == REF_newInvokeSpecial && isMethod())
1.336 +// flags += (IS_CONSTRUCTOR - IS_METHOD);
1.337 + return this;
1.338 + }
1.339 +
1.340 + private boolean testFlags(int mask, int value) {
1.341 + return (flags & mask) == value;
1.342 + }
1.343 + private boolean testAllFlags(int mask) {
1.344 + return testFlags(mask, mask);
1.345 + }
1.346 + private boolean testAnyFlags(int mask) {
1.347 + return !testFlags(mask, 0);
1.348 + }
1.349 +
1.350 + /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
1.351 + public boolean isMethodHandleInvoke() {
1.352 + final int bits = MH_INVOKE_MODS;
1.353 + final int negs = Modifier.STATIC;
1.354 + if (testFlags(bits | negs, bits) &&
1.355 + clazz == MethodHandle.class) {
1.356 + return isMethodHandleInvokeName(name);
1.357 + }
1.358 + return false;
1.359 + }
1.360 + public static boolean isMethodHandleInvokeName(String name) {
1.361 + return name.equals("invoke") || name.equals("invokeExact");
1.362 + }
1.363 + private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
1.364 +
1.365 + /** Utility method to query the modifier flags of this member. */
1.366 + public boolean isStatic() {
1.367 + return Modifier.isStatic(flags);
1.368 + }
1.369 + /** Utility method to query the modifier flags of this member. */
1.370 + public boolean isPublic() {
1.371 + return Modifier.isPublic(flags);
1.372 + }
1.373 + /** Utility method to query the modifier flags of this member. */
1.374 + public boolean isPrivate() {
1.375 + return Modifier.isPrivate(flags);
1.376 + }
1.377 + /** Utility method to query the modifier flags of this member. */
1.378 + public boolean isProtected() {
1.379 + return Modifier.isProtected(flags);
1.380 + }
1.381 + /** Utility method to query the modifier flags of this member. */
1.382 + public boolean isFinal() {
1.383 + return Modifier.isFinal(flags);
1.384 + }
1.385 + /** Utility method to query whether this member or its defining class is final. */
1.386 + public boolean canBeStaticallyBound() {
1.387 + return Modifier.isFinal(flags | clazz.getModifiers());
1.388 + }
1.389 + /** Utility method to query the modifier flags of this member. */
1.390 + public boolean isVolatile() {
1.391 + return Modifier.isVolatile(flags);
1.392 + }
1.393 + /** Utility method to query the modifier flags of this member. */
1.394 + public boolean isAbstract() {
1.395 + return Modifier.isAbstract(flags);
1.396 + }
1.397 + /** Utility method to query the modifier flags of this member. */
1.398 + public boolean isNative() {
1.399 + return Modifier.isNative(flags);
1.400 + }
1.401 + // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
1.402 +
1.403 + // unofficial modifier flags, used by HotSpot:
1.404 + static final int BRIDGE = 0x00000040;
1.405 + static final int VARARGS = 0x00000080;
1.406 + static final int SYNTHETIC = 0x00001000;
1.407 + static final int ANNOTATION= 0x00002000;
1.408 + static final int ENUM = 0x00004000;
1.409 + /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
1.410 + public boolean isBridge() {
1.411 + return testAllFlags(IS_METHOD | BRIDGE);
1.412 + }
1.413 + /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
1.414 + public boolean isVarargs() {
1.415 + return testAllFlags(VARARGS) && isInvocable();
1.416 + }
1.417 + /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
1.418 + public boolean isSynthetic() {
1.419 + return testAllFlags(SYNTHETIC);
1.420 + }
1.421 +
1.422 + static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
1.423 +
1.424 + // modifiers exported by the JVM:
1.425 + static final int RECOGNIZED_MODIFIERS = 0xFFFF;
1.426 +
1.427 + // private flags, not part of RECOGNIZED_MODIFIERS:
1.428 + static final int
1.429 + IS_METHOD = MN_IS_METHOD, // method (not constructor)
1.430 + IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
1.431 + IS_FIELD = MN_IS_FIELD, // field
1.432 + IS_TYPE = MN_IS_TYPE, // nested type
1.433 + CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
1.434 +
1.435 + static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
1.436 + static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
1.437 + static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
1.438 + static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
1.439 + static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
1.440 +
1.441 + /** Utility method to query whether this member is a method or constructor. */
1.442 + public boolean isInvocable() {
1.443 + return testAnyFlags(IS_INVOCABLE);
1.444 + }
1.445 + /** Utility method to query whether this member is a method, constructor, or field. */
1.446 + public boolean isFieldOrMethod() {
1.447 + return testAnyFlags(IS_FIELD_OR_METHOD);
1.448 + }
1.449 + /** Query whether this member is a method. */
1.450 + public boolean isMethod() {
1.451 + return testAllFlags(IS_METHOD);
1.452 + }
1.453 + /** Query whether this member is a constructor. */
1.454 + public boolean isConstructor() {
1.455 + return testAllFlags(IS_CONSTRUCTOR);
1.456 + }
1.457 + /** Query whether this member is a field. */
1.458 + public boolean isField() {
1.459 + return testAllFlags(IS_FIELD);
1.460 + }
1.461 + /** Query whether this member is a type. */
1.462 + public boolean isType() {
1.463 + return testAllFlags(IS_TYPE);
1.464 + }
1.465 + /** Utility method to query whether this member is neither public, private, nor protected. */
1.466 + public boolean isPackage() {
1.467 + return !testAnyFlags(ALL_ACCESS);
1.468 + }
1.469 + /** Query whether this member has a CallerSensitive annotation. */
1.470 + public boolean isCallerSensitive() {
1.471 + return testAllFlags(CALLER_SENSITIVE);
1.472 + }
1.473 +
1.474 + /** Utility method to query whether this member is accessible from a given lookup class. */
1.475 + public boolean isAccessibleFrom(Class<?> lookupClass) {
1.476 + return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
1.477 + lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
1.478 + }
1.479 +
1.480 + /** Initialize a query. It is not resolved. */
1.481 + private void init(Class<?> defClass, String name, Object type, int flags) {
1.482 + // defining class is allowed to be null (for a naked name/type pair)
1.483 + //name.toString(); // null check
1.484 + //type.equals(type); // null check
1.485 + // fill in fields:
1.486 + this.clazz = defClass;
1.487 + this.name = name;
1.488 + this.type = type;
1.489 + this.flags = flags;
1.490 + assert(testAnyFlags(ALL_KINDS));
1.491 + assert(this.resolution == null); // nobody should have touched this yet
1.492 + //assert(referenceKindIsConsistent()); // do this after resolution
1.493 + }
1.494 +
1.495 + /**
1.496 + * Calls down to the VM to fill in the fields. This method is
1.497 + * synchronized to avoid racing calls.
1.498 + */
1.499 + private void expandFromVM() {
1.500 + if (type != null) {
1.501 + return;
1.502 + }
1.503 + if (!isResolved()) {
1.504 + return;
1.505 + }
1.506 + MethodHandleNatives.expand(this);
1.507 + }
1.508 +
1.509 + // Capturing information from the Core Reflection API:
1.510 + private static int flagsMods(int flags, int mods, byte refKind) {
1.511 + assert((flags & RECOGNIZED_MODIFIERS) == 0);
1.512 + assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
1.513 + assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
1.514 + return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
1.515 + }
1.516 + /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
1.517 + public MemberName(Method m) {
1.518 + this(m, false);
1.519 + }
1.520 + @SuppressWarnings("LeakingThisInConstructor")
1.521 + public MemberName(Method m, boolean wantSpecial) {
1.522 + m.getClass(); // NPE check
1.523 + // fill in vmtarget, vmindex while we have m in hand:
1.524 + MethodHandleNatives.init(this, m);
1.525 + if (clazz == null) { // MHN.init failed
1.526 + if (m.getDeclaringClass() == MethodHandle.class &&
1.527 + isMethodHandleInvokeName(m.getName())) {
1.528 + // The JVM did not reify this signature-polymorphic instance.
1.529 + // Need a special case here.
1.530 + // See comments on MethodHandleNatives.linkMethod.
1.531 + MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
1.532 + int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
1.533 + init(MethodHandle.class, m.getName(), type, flags);
1.534 + if (isMethodHandleInvoke())
1.535 + return;
1.536 + }
1.537 + throw new LinkageError(m.toString());
1.538 + }
1.539 + assert(isResolved() && this.clazz != null);
1.540 + this.name = m.getName();
1.541 + if (this.type == null)
1.542 + this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
1.543 + if (wantSpecial) {
1.544 + if (isAbstract())
1.545 + throw new AbstractMethodError(this.toString());
1.546 + if (getReferenceKind() == REF_invokeVirtual)
1.547 + changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
1.548 + else if (getReferenceKind() == REF_invokeInterface)
1.549 + // invokeSpecial on a default method
1.550 + changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
1.551 + }
1.552 + }
1.553 + public MemberName asSpecial() {
1.554 + switch (getReferenceKind()) {
1.555 + case REF_invokeSpecial: return this;
1.556 + case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
1.557 + case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
1.558 + case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
1.559 + }
1.560 + throw new IllegalArgumentException(this.toString());
1.561 + }
1.562 + /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
1.563 + * In that case it must already be REF_invokeSpecial.
1.564 + */
1.565 + public MemberName asConstructor() {
1.566 + switch (getReferenceKind()) {
1.567 + case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
1.568 + case REF_newInvokeSpecial: return this;
1.569 + }
1.570 + throw new IllegalArgumentException(this.toString());
1.571 + }
1.572 + /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
1.573 + * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
1.574 + * The end result is to get a fully virtualized version of the MN.
1.575 + * (Note that resolving in the JVM will sometimes devirtualize, changing
1.576 + * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
1.577 + * in some corner cases to either of the previous two; this transform
1.578 + * undoes that change under the assumption that it occurred.)
1.579 + */
1.580 + public MemberName asNormalOriginal() {
1.581 + byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
1.582 + byte refKind = getReferenceKind();
1.583 + byte newRefKind = refKind;
1.584 + MemberName result = this;
1.585 + switch (refKind) {
1.586 + case REF_invokeInterface:
1.587 + case REF_invokeVirtual:
1.588 + case REF_invokeSpecial:
1.589 + newRefKind = normalVirtual;
1.590 + break;
1.591 + }
1.592 + if (newRefKind == refKind)
1.593 + return this;
1.594 + result = clone().changeReferenceKind(newRefKind, refKind);
1.595 + assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
1.596 + return result;
1.597 + }
1.598 + /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
1.599 + @SuppressWarnings("LeakingThisInConstructor")
1.600 + public MemberName(Constructor<?> ctor) {
1.601 + ctor.getClass(); // NPE check
1.602 + // fill in vmtarget, vmindex while we have ctor in hand:
1.603 + MethodHandleNatives.init(this, ctor);
1.604 + assert(isResolved() && this.clazz != null);
1.605 + this.name = CONSTRUCTOR_NAME;
1.606 + if (this.type == null)
1.607 + this.type = new Object[] { void.class, ctor.getParameterTypes() };
1.608 + }
1.609 + /** Create a name for the given reflected field. The resulting name will be in a resolved state.
1.610 + */
1.611 + public MemberName(Field fld) {
1.612 + this(fld, false);
1.613 + }
1.614 + @SuppressWarnings("LeakingThisInConstructor")
1.615 + public MemberName(Field fld, boolean makeSetter) {
1.616 + fld.getClass(); // NPE check
1.617 + // fill in vmtarget, vmindex while we have fld in hand:
1.618 + MethodHandleNatives.init(this, fld);
1.619 + assert(isResolved() && this.clazz != null);
1.620 + this.name = fld.getName();
1.621 + this.type = fld.getType();
1.622 + assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
1.623 + byte refKind = this.getReferenceKind();
1.624 + assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
1.625 + if (makeSetter) {
1.626 + changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
1.627 + }
1.628 + }
1.629 + public boolean isGetter() {
1.630 + return MethodHandleNatives.refKindIsGetter(getReferenceKind());
1.631 + }
1.632 + public boolean isSetter() {
1.633 + return MethodHandleNatives.refKindIsSetter(getReferenceKind());
1.634 + }
1.635 + public MemberName asSetter() {
1.636 + byte refKind = getReferenceKind();
1.637 + assert(MethodHandleNatives.refKindIsGetter(refKind));
1.638 + assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
1.639 + byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
1.640 + return clone().changeReferenceKind(setterRefKind, refKind);
1.641 + }
1.642 + /** Create a name for the given class. The resulting name will be in a resolved state. */
1.643 + public MemberName(Class<?> type) {
1.644 + init(type.getDeclaringClass(), type.getSimpleName(), type,
1.645 + flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
1.646 + initResolved(true);
1.647 + }
1.648 +
1.649 + /**
1.650 + * Create a name for a signature-polymorphic invoker.
1.651 + * This is a placeholder for a signature-polymorphic instance
1.652 + * (of MH.invokeExact, etc.) that the JVM does not reify.
1.653 + * See comments on {@link MethodHandleNatives#linkMethod}.
1.654 + */
1.655 + static MemberName makeMethodHandleInvoke(String name, MethodType type) {
1.656 + return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
1.657 + }
1.658 + static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
1.659 + MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
1.660 + mem.flags |= mods; // it's not resolved, but add these modifiers anyway
1.661 + assert(mem.isMethodHandleInvoke()) : mem;
1.662 + return mem;
1.663 + }
1.664 +
1.665 + // bare-bones constructor; the JVM will fill it in
1.666 + MemberName() { }
1.667 +
1.668 + // locally useful cloner
1.669 + @Override protected MemberName clone() {
1.670 + try {
1.671 + return (MemberName) super.clone();
1.672 + } catch (CloneNotSupportedException ex) {
1.673 + throw newInternalError(ex);
1.674 + }
1.675 + }
1.676 +
1.677 + /** Get the definition of this member name.
1.678 + * This may be in a super-class of the declaring class of this member.
1.679 + */
1.680 + public MemberName getDefinition() {
1.681 + if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
1.682 + if (isType()) return this;
1.683 + MemberName res = this.clone();
1.684 + res.clazz = null;
1.685 + res.type = null;
1.686 + res.name = null;
1.687 + res.resolution = res;
1.688 + res.expandFromVM();
1.689 + assert(res.getName().equals(this.getName()));
1.690 + return res;
1.691 + }
1.692 +
1.693 + @Override
1.694 + public int hashCode() {
1.695 + return Objects.hash(clazz, getReferenceKind(), name, getType());
1.696 + }
1.697 + @Override
1.698 + public boolean equals(Object that) {
1.699 + return (that instanceof MemberName && this.equals((MemberName)that));
1.700 + }
1.701 +
1.702 + /** Decide if two member names have exactly the same symbolic content.
1.703 + * Does not take into account any actual class members, so even if
1.704 + * two member names resolve to the same actual member, they may
1.705 + * be distinct references.
1.706 + */
1.707 + public boolean equals(MemberName that) {
1.708 + if (this == that) return true;
1.709 + if (that == null) return false;
1.710 + return this.clazz == that.clazz
1.711 + && this.getReferenceKind() == that.getReferenceKind()
1.712 + && Objects.equals(this.name, that.name)
1.713 + && Objects.equals(this.getType(), that.getType());
1.714 + }
1.715 +
1.716 + // Construction from symbolic parts, for queries:
1.717 + /** Create a field or type name from the given components:
1.718 + * Declaring class, name, type, reference kind.
1.719 + * The declaring class may be supplied as null if this is to be a bare name and type.
1.720 + * The resulting name will in an unresolved state.
1.721 + */
1.722 + public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
1.723 + init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
1.724 + initResolved(false);
1.725 + }
1.726 + /** Create a field or type name from the given components: Declaring class, name, type.
1.727 + * The declaring class may be supplied as null if this is to be a bare name and type.
1.728 + * The modifier flags default to zero.
1.729 + * The resulting name will in an unresolved state.
1.730 + */
1.731 + public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
1.732 + this(defClass, name, type, REF_NONE);
1.733 + initResolved(false);
1.734 + }
1.735 + /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
1.736 + * It will be a constructor if and only if the name is {@code "<init>"}.
1.737 + * The declaring class may be supplied as null if this is to be a bare name and type.
1.738 + * The last argument is optional, a boolean which requests REF_invokeSpecial.
1.739 + * The resulting name will in an unresolved state.
1.740 + */
1.741 + public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
1.742 + int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
1.743 + init(defClass, name, type, flagsMods(initFlags, 0, refKind));
1.744 + initResolved(false);
1.745 + }
1.746 + /** Create a method, constructor, or field name from the given components:
1.747 + * Reference kind, declaring class, name, type.
1.748 + */
1.749 + public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
1.750 + int kindFlags;
1.751 + if (MethodHandleNatives.refKindIsField(refKind)) {
1.752 + kindFlags = IS_FIELD;
1.753 + if (!(type instanceof Class))
1.754 + throw newIllegalArgumentException("not a field type");
1.755 + } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
1.756 + kindFlags = IS_METHOD;
1.757 + if (!(type instanceof MethodType))
1.758 + throw newIllegalArgumentException("not a method type");
1.759 + } else if (refKind == REF_newInvokeSpecial) {
1.760 + kindFlags = IS_CONSTRUCTOR;
1.761 + if (!(type instanceof MethodType) ||
1.762 + !CONSTRUCTOR_NAME.equals(name))
1.763 + throw newIllegalArgumentException("not a constructor type or name");
1.764 + } else {
1.765 + throw newIllegalArgumentException("bad reference kind "+refKind);
1.766 + }
1.767 + init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
1.768 + initResolved(false);
1.769 + }
1.770 + /** Query whether this member name is resolved to a non-static, non-final method.
1.771 + */
1.772 + public boolean hasReceiverTypeDispatch() {
1.773 + return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
1.774 + }
1.775 +
1.776 + /** Query whether this member name is resolved.
1.777 + * A resolved member name is one for which the JVM has found
1.778 + * a method, constructor, field, or type binding corresponding exactly to the name.
1.779 + * (Document?)
1.780 + */
1.781 + public boolean isResolved() {
1.782 + return resolution == null;
1.783 + }
1.784 +
1.785 + private void initResolved(boolean isResolved) {
1.786 + assert(this.resolution == null); // not initialized yet!
1.787 + if (!isResolved)
1.788 + this.resolution = this;
1.789 + assert(isResolved() == isResolved);
1.790 + }
1.791 +
1.792 + void checkForTypeAlias() {
1.793 + if (isInvocable()) {
1.794 + MethodType type;
1.795 + if (this.type instanceof MethodType)
1.796 + type = (MethodType) this.type;
1.797 + else
1.798 + this.type = type = getMethodType();
1.799 + if (type.erase() == type) return;
1.800 + if (VerifyAccess.isTypeVisible(type, clazz)) return;
1.801 + throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
1.802 + } else {
1.803 + Class<?> type;
1.804 + if (this.type instanceof Class<?>)
1.805 + type = (Class<?>) this.type;
1.806 + else
1.807 + this.type = type = getFieldType();
1.808 + if (VerifyAccess.isTypeVisible(type, clazz)) return;
1.809 + throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
1.810 + }
1.811 + }
1.812 +
1.813 +
1.814 + /** Produce a string form of this member name.
1.815 + * For types, it is simply the type's own string (as reported by {@code toString}).
1.816 + * For fields, it is {@code "DeclaringClass.name/type"}.
1.817 + * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
1.818 + * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
1.819 + * If the member is unresolved, a prefix {@code "*."} is prepended.
1.820 + */
1.821 + @SuppressWarnings("LocalVariableHidesMemberVariable")
1.822 + @Override
1.823 + public String toString() {
1.824 + if (isType())
1.825 + return type.toString(); // class java.lang.String
1.826 + // else it is a field, method, or constructor
1.827 + StringBuilder buf = new StringBuilder();
1.828 + if (getDeclaringClass() != null) {
1.829 + buf.append(getName(clazz));
1.830 + buf.append('.');
1.831 + }
1.832 + String name = getName();
1.833 + buf.append(name == null ? "*" : name);
1.834 + Object type = getType();
1.835 + if (!isInvocable()) {
1.836 + buf.append('/');
1.837 + buf.append(type == null ? "*" : getName(type));
1.838 + } else {
1.839 + buf.append(type == null ? "(*)*" : getName(type));
1.840 + }
1.841 + byte refKind = getReferenceKind();
1.842 + if (refKind != REF_NONE) {
1.843 + buf.append('/');
1.844 + buf.append(MethodHandleNatives.refKindName(refKind));
1.845 + }
1.846 + //buf.append("#").append(System.identityHashCode(this));
1.847 + return buf.toString();
1.848 + }
1.849 + private static String getName(Object obj) {
1.850 + if (obj instanceof Class<?>)
1.851 + return ((Class<?>)obj).getName();
1.852 + return String.valueOf(obj);
1.853 + }
1.854 +
1.855 + public IllegalAccessException makeAccessException(String message, Object from) {
1.856 + message = message + ": "+ toString();
1.857 + if (from != null) message += ", from " + from;
1.858 + return new IllegalAccessException(message);
1.859 + }
1.860 + private String message() {
1.861 + if (isResolved())
1.862 + return "no access";
1.863 + else if (isConstructor())
1.864 + return "no such constructor";
1.865 + else if (isMethod())
1.866 + return "no such method";
1.867 + else
1.868 + return "no such field";
1.869 + }
1.870 + public ReflectiveOperationException makeAccessException() {
1.871 + String message = message() + ": "+ toString();
1.872 + ReflectiveOperationException ex;
1.873 + if (isResolved() || !(resolution instanceof NoSuchMethodError ||
1.874 + resolution instanceof NoSuchFieldError))
1.875 + ex = new IllegalAccessException(message);
1.876 + else if (isConstructor())
1.877 + ex = new NoSuchMethodException(message);
1.878 + else if (isMethod())
1.879 + ex = new NoSuchMethodException(message);
1.880 + else
1.881 + ex = new NoSuchFieldException(message);
1.882 + if (resolution instanceof Throwable)
1.883 + ex.initCause((Throwable) resolution);
1.884 + return ex;
1.885 + }
1.886 +
1.887 + /** Actually making a query requires an access check. */
1.888 + /*non-public*/ static Factory getFactory() {
1.889 + return Factory.INSTANCE;
1.890 + }
1.891 + /** A factory type for resolving member names with the help of the VM.
1.892 + * TBD: Define access-safe public constructors for this factory.
1.893 + */
1.894 + /*non-public*/ static class Factory {
1.895 + private Factory() { } // singleton pattern
1.896 + static Factory INSTANCE = new Factory();
1.897 +
1.898 + private static int ALLOWED_FLAGS = ALL_KINDS;
1.899 +
1.900 + /// Queries
1.901 + List<MemberName> getMembers(Class<?> defc,
1.902 + String matchName, Object matchType,
1.903 + int matchFlags, Class<?> lookupClass) {
1.904 + matchFlags &= ALLOWED_FLAGS;
1.905 + String matchSig = null;
1.906 + if (matchType != null) {
1.907 + matchSig = BytecodeDescriptor.unparse(matchType);
1.908 + if (matchSig.startsWith("("))
1.909 + matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
1.910 + else
1.911 + matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
1.912 + }
1.913 + final int BUF_MAX = 0x2000;
1.914 + int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
1.915 + MemberName[] buf = newMemberBuffer(len1);
1.916 + int totalCount = 0;
1.917 + ArrayList<MemberName[]> bufs = null;
1.918 + int bufCount = 0;
1.919 + for (;;) {
1.920 + bufCount = MethodHandleNatives.getMembers(defc,
1.921 + matchName, matchSig, matchFlags,
1.922 + lookupClass,
1.923 + totalCount, buf);
1.924 + if (bufCount <= buf.length) {
1.925 + if (bufCount < 0) bufCount = 0;
1.926 + totalCount += bufCount;
1.927 + break;
1.928 + }
1.929 + // JVM returned to us with an intentional overflow!
1.930 + totalCount += buf.length;
1.931 + int excess = bufCount - buf.length;
1.932 + if (bufs == null) bufs = new ArrayList<>(1);
1.933 + bufs.add(buf);
1.934 + int len2 = buf.length;
1.935 + len2 = Math.max(len2, excess);
1.936 + len2 = Math.max(len2, totalCount / 4);
1.937 + buf = newMemberBuffer(Math.min(BUF_MAX, len2));
1.938 + }
1.939 + ArrayList<MemberName> result = new ArrayList<>(totalCount);
1.940 + if (bufs != null) {
1.941 + for (MemberName[] buf0 : bufs) {
1.942 + Collections.addAll(result, buf0);
1.943 + }
1.944 + }
1.945 + result.addAll(Arrays.asList(buf).subList(0, bufCount));
1.946 + // Signature matching is not the same as type matching, since
1.947 + // one signature might correspond to several types.
1.948 + // So if matchType is a Class or MethodType, refilter the results.
1.949 + if (matchType != null && matchType != matchSig) {
1.950 + for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
1.951 + MemberName m = it.next();
1.952 + if (!matchType.equals(m.getType()))
1.953 + it.remove();
1.954 + }
1.955 + }
1.956 + return result;
1.957 + }
1.958 + /** Produce a resolved version of the given member.
1.959 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.960 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.961 + * If lookup fails or access is not permitted, null is returned.
1.962 + * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1.963 + */
1.964 + private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
1.965 + MemberName m = ref.clone(); // JVM will side-effect the ref
1.966 + assert(refKind == m.getReferenceKind());
1.967 + try {
1.968 + m = MethodHandleNatives.resolve(m, lookupClass);
1.969 + m.checkForTypeAlias();
1.970 + m.resolution = null;
1.971 + } catch (LinkageError ex) {
1.972 + // JVM reports that the "bytecode behavior" would get an error
1.973 + assert(!m.isResolved());
1.974 + m.resolution = ex;
1.975 + return m;
1.976 + }
1.977 + assert(m.referenceKindIsConsistent());
1.978 + m.initResolved(true);
1.979 + assert(m.vminfoIsConsistent());
1.980 + return m;
1.981 + }
1.982 + /** Produce a resolved version of the given member.
1.983 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.984 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.985 + * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
1.986 + * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1.987 + */
1.988 + public
1.989 + <NoSuchMemberException extends ReflectiveOperationException>
1.990 + MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1.991 + Class<NoSuchMemberException> nsmClass)
1.992 + throws IllegalAccessException, NoSuchMemberException {
1.993 + MemberName result = resolve(refKind, m, lookupClass);
1.994 + if (result.isResolved())
1.995 + return result;
1.996 + ReflectiveOperationException ex = result.makeAccessException();
1.997 + if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
1.998 + throw nsmClass.cast(ex);
1.999 + }
1.1000 + /** Produce a resolved version of the given member.
1.1001 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1002 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1003 + * If lookup fails or access is not permitted, return null.
1.1004 + * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1.1005 + */
1.1006 + public
1.1007 + MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1.1008 + MemberName result = resolve(refKind, m, lookupClass);
1.1009 + if (result.isResolved())
1.1010 + return result;
1.1011 + return null;
1.1012 + }
1.1013 + /** Return a list of all methods defined by the given class.
1.1014 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1015 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1016 + * Inaccessible members are not added to the last.
1.1017 + */
1.1018 + public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1.1019 + Class<?> lookupClass) {
1.1020 + return getMethods(defc, searchSupers, null, null, lookupClass);
1.1021 + }
1.1022 + /** Return a list of matching methods defined by the given class.
1.1023 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1024 + * Returned methods will match the name (if not null) and the type (if not null).
1.1025 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1026 + * Inaccessible members are not added to the last.
1.1027 + */
1.1028 + public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1.1029 + String name, MethodType type, Class<?> lookupClass) {
1.1030 + int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1.1031 + return getMembers(defc, name, type, matchFlags, lookupClass);
1.1032 + }
1.1033 + /** Return a list of all constructors defined by the given class.
1.1034 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1035 + * Inaccessible members are not added to the last.
1.1036 + */
1.1037 + public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
1.1038 + return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
1.1039 + }
1.1040 + /** Return a list of all fields defined by the given class.
1.1041 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1042 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1043 + * Inaccessible members are not added to the last.
1.1044 + */
1.1045 + public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1.1046 + Class<?> lookupClass) {
1.1047 + return getFields(defc, searchSupers, null, null, lookupClass);
1.1048 + }
1.1049 + /** Return a list of all fields defined by the given class.
1.1050 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1051 + * Returned fields will match the name (if not null) and the type (if not null).
1.1052 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1053 + * Inaccessible members are not added to the last.
1.1054 + */
1.1055 + public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1.1056 + String name, Class<?> type, Class<?> lookupClass) {
1.1057 + int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1.1058 + return getMembers(defc, name, type, matchFlags, lookupClass);
1.1059 + }
1.1060 + /** Return a list of all nested types defined by the given class.
1.1061 + * Super types are searched (for inherited members) if {@code searchSupers} is true.
1.1062 + * Access checking is performed on behalf of the given {@code lookupClass}.
1.1063 + * Inaccessible members are not added to the last.
1.1064 + */
1.1065 + public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1.1066 + Class<?> lookupClass) {
1.1067 + int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1.1068 + return getMembers(defc, null, null, matchFlags, lookupClass);
1.1069 + }
1.1070 + private static MemberName[] newMemberBuffer(int length) {
1.1071 + MemberName[] buf = new MemberName[length];
1.1072 + // fill the buffer with dummy structs for the JVM to fill in
1.1073 + for (int i = 0; i < length; i++)
1.1074 + buf[i] = new MemberName();
1.1075 + return buf;
1.1076 + }
1.1077 + }
1.1078 +
1.1079 +// static {
1.1080 +// System.out.println("Hello world! My methods are:");
1.1081 +// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
1.1082 +// }
1.1083 +}