1 /* 2 * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import sun.invoke.util.BytecodeDescriptor; 29 import sun.invoke.util.VerifyAccess; 30 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.Method; 34 import java.lang.reflect.Member; 35 import java.lang.reflect.Modifier; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.Collections; 39 import java.util.Iterator; 40 import java.util.List; 41 42 import static java.lang.invoke.MethodHandleNatives.Constants.*; 43 import static java.lang.invoke.MethodHandleStatics.*; 44 45 import sun.misc.JavaLangAccess; 46 import sun.misc.SharedSecrets; 47 48 import java.util.Objects; 49 50 /** 51 * A {@code MemberName} is a compact symbolic datum which fully characterizes 52 * a method or field reference. 53 * A member name refers to a field, method, constructor, or member type. 54 * Every member name has a simple name (a string) and a type (either a Class or MethodType). 55 * A member name may also have a non-null declaring class, or it may be simply 56 * a naked name/type pair. 57 * A member name may also have non-zero modifier flags. 58 * Finally, a member name may be either resolved or unresolved. 59 * If it is resolved, the existence of the named 60 * <p> 61 * Whether resolved or not, a member name provides no access rights or 62 * invocation capability to its possessor. It is merely a compact 63 * representation of all symbolic information necessary to link to 64 * and properly use the named member. 65 * <p> 66 * When resolved, a member name's internal implementation may include references to JVM metadata. 67 * This representation is stateless and only descriptive. 68 * It provides no private information and no capability to use the member. 69 * <p> 70 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information 71 * about the internals of a method (except its bytecodes) and also 72 * allows invocation. A MemberName is much lighter than a Method, 73 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), 74 * and those seven fields omit much of the information in Method. 75 * @author jrose 76 */ 77 @SuppressWarnings("rawtypes") //Comparable in next line 78 /*non-public*/ final class MemberName implements Member, Comparable, Cloneable { 79 private Class<?> clazz; // class in which the method is defined 80 private String name; // may be null if not yet materialized 81 private Object type; // may be null if not yet materialized 82 private int flags; // modifier bits; see reflect.Modifier 83 //@Injected JVM_Method* vmtarget; 84 //@Injected int vmindex; 85 private Object resolution; // if null, this guy is resolved 86 87 private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 88 89 // bare-bones constructor; the JVM will fill it in 90 MemberName() { } 91 92 /** Create a name for the given class. The resulting name will be in a resolved state. */ 93 public MemberName(Class<?> type) { 94 init(type.getDeclaringClass(), type.getSimpleName(), type, 95 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); 96 initResolved(true); 97 } 98 99 // Construction from symbolic parts, for queries: 100 /** Create a field or type name from the given components: 101 * Declaring class, name, type, reference kind. 102 * The declaring class may be supplied as null if this is to be a bare name and type. 103 * The resulting name will in an unresolved state. 104 */ 105 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { 106 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); 107 initResolved(false); 108 } 109 110 /** Create a field or type name from the given components: Declaring class, name, type. 111 * The declaring class may be supplied as null if this is to be a bare name and type. 112 * The modifier flags default to zero. 113 * The resulting name will in an unresolved state. 114 */ 115 public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) { 116 this(defClass, name, type, REF_NONE); 117 initResolved(false); 118 } 119 120 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. 121 * It will be a constructor if and only if the name is {@code "<init>"}. 122 * The declaring class may be supplied as null if this is to be a bare name and type. 123 * The last argument is optional, a boolean which requests REF_invokeSpecial. 124 * The resulting name will in an unresolved state. 125 */ 126 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { 127 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); 128 init(defClass, name, type, flagsMods(initFlags, 0, refKind)); 129 initResolved(false); 130 } 131 132 /** Create a method, constructor, or field name from the given components: 133 * Reference kind, declaring class, name, type. 134 */ 135 public MemberName(byte refKind, Class<?> defClass, String name, Object type) { 136 int kindFlags; 137 if (MethodHandleNatives.refKindIsField(refKind)) { 138 kindFlags = IS_FIELD; 139 if (!(type instanceof Class)) 140 throw newIllegalArgumentException("not a field type"); 141 } else if (MethodHandleNatives.refKindIsMethod(refKind)) { 142 kindFlags = IS_METHOD; 143 if (!(type instanceof MethodType)) 144 throw newIllegalArgumentException("not a method type"); 145 } else if (refKind == REF_newInvokeSpecial) { 146 kindFlags = IS_CONSTRUCTOR; 147 if (!(type instanceof MethodType) || 148 !CONSTRUCTOR_NAME.equals(name)) 149 throw newIllegalArgumentException("not a constructor type or name"); 150 } else { 151 throw newIllegalArgumentException("bad reference kind "+refKind); 152 } 153 init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); 154 initResolved(false); 155 } 156 157 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ 158 public static MemberName make(Method m) { 159 return make(m, false); 160 } 161 162 @SuppressWarnings("LeakingThisInConstructor") 163 private MemberName(Method m, boolean wantSpecial) { 164 m.getClass(); // NPE check 165 // fill in vmtarget, vmindex while we have m in hand: 166 MethodHandleNatives.init(this, m); 167 if (clazz == null) { // MHN.init failed 168 if (m.getDeclaringClass() == MethodHandle.class && 169 isMethodHandleInvokeName(m.getName())) { 170 // The JVM did not reify this signature-polymorphic instance. 171 // Need a special case here. 172 // See comments on MethodHandleNatives.linkMethod. 173 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); 174 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); 175 init(MethodHandle.class, m.getName(), type, flags); 176 if (isMethodHandleInvoke()) { 177 return; 178 } 179 } 180 throw new LinkageError(m.toString()); 181 } 182 assert(isResolved() && this.clazz != null); 183 this.name = m.getName(); 184 if (this.type == null) { 185 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; 186 } 187 if (wantSpecial) { 188 if (isAbstract()) { 189 throw new AbstractMethodError(this.toString()); 190 } 191 if (getReferenceKind() == REF_invokeVirtual) { 192 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); 193 } else if (getReferenceKind() == REF_invokeInterface) { 194 // invokeSpecial on a default method 195 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); 196 } 197 } 198 } 199 200 public static MemberName make(Method m, boolean wantSpecial) { 201 // Unreflected member names are resolved so intern them here. 202 MemberName tmp0 = null; 203 InternTransaction tx = new InternTransaction(m.getDeclaringClass()); 204 while (tmp0 == null) { 205 MemberName tmp = new MemberName(m, wantSpecial); 206 tmp0 = tx.tryIntern(tmp); 207 } 208 return tmp0; 209 } 210 211 /** 212 * Create a name for the given reflected constructor. The resulting name 213 * will be in a resolved state. 214 */ 215 @SuppressWarnings("LeakingThisInConstructor") 216 private MemberName(Constructor<?> ctor) { 217 ctor.getClass(); // NPE check 218 // fill in vmtarget, vmindex while we have ctor in hand: 219 MethodHandleNatives.init(this, ctor); 220 assert(isResolved() && this.clazz != null); 221 this.name = CONSTRUCTOR_NAME; 222 if (this.type == null) { 223 this.type = new Object[] { void.class, ctor.getParameterTypes() }; 224 } 225 } 226 227 public static MemberName make(Constructor<?> ctor) { 228 // Unreflected member names are resolved so intern them here. 229 MemberName tmp0 = null; 230 InternTransaction tx = new InternTransaction(ctor.getDeclaringClass()); 231 while (tmp0 == null) { 232 MemberName tmp = new MemberName(ctor); 233 tmp0 = tx.tryIntern(tmp); 234 } 235 return tmp0; 236 } 237 238 /** Create a name for the given reflected field. The resulting name will be in a resolved state. 239 */ 240 public static MemberName make(Field field) { 241 return make(field, false); 242 } 243 244 @SuppressWarnings("LeakingThisInConstructor") 245 private MemberName(Field field, boolean makeSetter) { 246 field.getClass(); // NPE check 247 // fill in vmtarget, vmindex while we have field in hand: 248 MethodHandleNatives.init(this, field); 249 assert(isResolved() && this.clazz != null); 250 this.name = field.getName(); 251 this.type = field.getType(); 252 byte refKind = this.getReferenceKind(); 253 assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); 254 if (makeSetter) { 255 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 256 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); 257 } 258 } 259 260 public static MemberName make(Field field, boolean makeSetter) { 261 // Unreflected member names are resolved so intern them here. 262 MemberName tmp0 = null; 263 InternTransaction tx = new InternTransaction(field.getDeclaringClass()); 264 while (tmp0 == null) { 265 MemberName tmp = new MemberName(field, makeSetter); 266 tmp0 = tx.tryIntern(tmp); 267 } 268 return tmp0; 269 } 270 271 /** Initialize a query. It is not resolved. */ 272 private void init(Class<?> defClass, String name, Object type, int flags) { 273 // defining class is allowed to be null (for a naked name/type pair) 274 //name.toString(); // null check 275 //type.equals(type); // null check 276 // fill in fields: 277 this.clazz = defClass; 278 this.name = name; 279 this.type = type; 280 this.flags = flags; 281 assert(testAnyFlags(ALL_KINDS)); 282 assert(this.resolution == null); // nobody should have touched this yet 283 //assert(referenceKindIsConsistent()); // do this after resolution 284 } 285 286 private void initResolved(boolean isResolved) { 287 assert(this.resolution == null); // not initialized yet! 288 if (!isResolved) 289 this.resolution = this; 290 assert(isResolved() == isResolved); 291 } 292 293 /** 294 * Helper method to intern this member name in the declaring class' member name table. 295 */ 296 @SuppressWarnings("unchecked") 297 private MemberName intern(int transaction_token) { 298 return jla.internMemberName(clazz, this, transaction_token); 299 } 300 301 /** 302 * Helper method to obtain the transaction token for interning, 303 * given Class clazz. 304 * @param clazz 305 * @return 306 */ 307 static private int internTxnToken(Class clazz) { 308 return clazz == null ? 0 : jla.getClassRedefinedCount(clazz); 309 } 310 311 /** 312 * Helper method to obtain the transaction token for interning, given this. 313 * @return 314 */ 315 private int internTxnToken() { 316 return internTxnToken(clazz); 317 } 318 319 /** 320 * Helper method to conditionally intern cloned+modified member names. 321 */ 322 private MemberName intern(MemberName likeThis, int transaction_token) { 323 if (likeThis.isResolved()) 324 return intern(transaction_token); 325 else 326 return this; 327 } 328 329 /** 330 * Helper class to handle the case where the class checked for no 331 * redefinition may not be correct; resolution can end up with a different 332 * class. 333 */ 334 static class InternTransaction { 335 Class<?> tx_class; 336 int txn_token; 337 338 InternTransaction(Class<?> tx_class) { 339 this.tx_class = tx_class; 340 this.txn_token = internTxnToken(tx_class); 341 } 342 343 /** 344 * If member_name is not resolved, returns member_name; if is resolved, 345 * attempts to intern member_name (once) while checking for races. 346 * 347 * @param member_name 348 * @return member_name if not resolved, null if racing, otherwise 349 * value of interned member_name. 350 */ 351 MemberName tryIntern(MemberName member_name) { 352 if (member_name.isResolved()) { 353 if (member_name.getClass() != tx_class) { 354 Class prev_tx_class = tx_class; 355 int prev_txn_token = txn_token; 356 tx_class = member_name.getClass(); 357 txn_token = internTxnToken(tx_class); 358 // Zero is a special case. 359 if (txn_token != 0 || 360 prev_txn_token != internTxnToken(prev_tx_class)) { 361 // Resolved class is different and at least one 362 // redef of it occurred, therefore repeat with 363 // proper class for race consistency checking. 364 return null; 365 } 366 } 367 return member_name.intern(txn_token); 368 } else { 369 return member_name; 370 } 371 } 372 } 373 374 /** Return the declaring class of this member. 375 * In the case of a bare name and type, the declaring class will be null. 376 */ 377 @Override 378 public Class<?> getDeclaringClass() { 379 return clazz; 380 } 381 382 /** Utility method producing the class loader of the declaring class. */ 383 public ClassLoader getClassLoader() { 384 return clazz.getClassLoader(); 385 } 386 387 /** Return the simple name of this member. 388 * For a type, it is the same as {@link Class#getSimpleName}. 389 * For a method or field, it is the simple name of the member. 390 * For a constructor, it is always {@code "<init>"}. 391 */ 392 @Override 393 public String getName() { 394 if (name == null) { 395 expandFromVM(); 396 if (name == null) { 397 return null; 398 } 399 } 400 return name; 401 } 402 403 public MethodType getMethodOrFieldType() { 404 if (isInvocable()) 405 return getMethodType(); 406 if (isGetter()) 407 return MethodType.methodType(getFieldType()); 408 if (isSetter()) 409 return MethodType.methodType(void.class, getFieldType()); 410 throw new InternalError("not a method or field: "+this); 411 } 412 413 /** Return the declared type of this member, which 414 * must be a method or constructor. 415 */ 416 public MethodType getMethodType() { 417 if (type == null) { 418 expandFromVM(); 419 if (type == null) { 420 return null; 421 } 422 } 423 if (!isInvocable()) { 424 throw newIllegalArgumentException("not invocable, no method type"); 425 } 426 427 { 428 // Get a snapshot of type which doesn't get changed by racing threads. 429 final Object type = this.type; 430 if (type instanceof MethodType) { 431 return (MethodType) type; 432 } 433 } 434 435 // type is not a MethodType yet. Convert it thread-safely. 436 synchronized (this) { 437 if (type instanceof String) { 438 String sig = (String) type; 439 MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader()); 440 type = res; 441 } else if (type instanceof Object[]) { 442 Object[] typeInfo = (Object[]) type; 443 Class<?>[] ptypes = (Class<?>[]) typeInfo[1]; 444 Class<?> rtype = (Class<?>) typeInfo[0]; 445 MethodType res = MethodType.methodType(rtype, ptypes); 446 type = res; 447 } 448 // Make sure type is a MethodType for racing threads. 449 assert type instanceof MethodType : "bad method type " + type; 450 } 451 return (MethodType) type; 452 } 453 454 /** Return the actual type under which this method or constructor must be invoked. 455 * For non-static methods or constructors, this is the type with a leading parameter, 456 * a reference to declaring class. For static methods, it is the same as the declared type. 457 */ 458 public MethodType getInvocationType() { 459 MethodType itype = getMethodOrFieldType(); 460 if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial) 461 return itype.changeReturnType(clazz); 462 if (!isStatic()) 463 return itype.insertParameterTypes(0, clazz); 464 return itype; 465 } 466 467 /** Utility method producing the parameter types of the method type. */ 468 public Class<?>[] getParameterTypes() { 469 return getMethodType().parameterArray(); 470 } 471 472 /** Utility method producing the return type of the method type. */ 473 public Class<?> getReturnType() { 474 return getMethodType().returnType(); 475 } 476 477 /** Return the declared type of this member, which 478 * must be a field or type. 479 * If it is a type member, that type itself is returned. 480 */ 481 public Class<?> getFieldType() { 482 if (type == null) { 483 expandFromVM(); 484 if (type == null) { 485 return null; 486 } 487 } 488 if (isInvocable()) { 489 throw newIllegalArgumentException("not a field or nested class, no simple type"); 490 } 491 492 { 493 // Get a snapshot of type which doesn't get changed by racing threads. 494 final Object type = this.type; 495 if (type instanceof Class<?>) { 496 return (Class<?>) type; 497 } 498 } 499 500 // type is not a Class yet. Convert it thread-safely. 501 synchronized (this) { 502 if (type instanceof String) { 503 String sig = (String) type; 504 MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader()); 505 Class<?> res = mtype.returnType(); 506 type = res; 507 } 508 // Make sure type is a Class for racing threads. 509 assert type instanceof Class<?> : "bad field type " + type; 510 } 511 return (Class<?>) type; 512 } 513 514 /** Utility method to produce either the method type or field type of this member. */ 515 public Object getType() { 516 return (isInvocable() ? getMethodType() : getFieldType()); 517 } 518 519 /** Utility method to produce the signature of this member, 520 * used within the class file format to describe its type. 521 */ 522 public String getSignature() { 523 if (type == null) { 524 expandFromVM(); 525 if (type == null) { 526 return null; 527 } 528 } 529 if (isInvocable()) 530 return BytecodeDescriptor.unparse(getMethodType()); 531 else 532 return BytecodeDescriptor.unparse(getFieldType()); 533 } 534 535 /** Return the modifier flags of this member. 536 * @see java.lang.reflect.Modifier 537 */ 538 @Override 539 public int getModifiers() { 540 return (flags & RECOGNIZED_MODIFIERS); 541 } 542 543 /** Return the reference kind of this member, or zero if none. 544 */ 545 public byte getReferenceKind() { 546 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK); 547 } 548 private boolean referenceKindIsConsistent() { 549 byte refKind = getReferenceKind(); 550 if (refKind == REF_NONE) return isType(); 551 if (isField()) { 552 assert(staticIsConsistent()); 553 assert(MethodHandleNatives.refKindIsField(refKind)); 554 } else if (isConstructor()) { 555 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial); 556 } else if (isMethod()) { 557 assert(staticIsConsistent()); 558 assert(MethodHandleNatives.refKindIsMethod(refKind)); 559 if (clazz.isInterface()) 560 assert(refKind == REF_invokeInterface || 561 refKind == REF_invokeStatic || 562 refKind == REF_invokeSpecial || 563 refKind == REF_invokeVirtual && isObjectPublicMethod()); 564 } else { 565 assert(false); 566 } 567 return true; 568 } 569 private boolean isObjectPublicMethod() { 570 if (clazz == Object.class) return true; 571 MethodType mtype = getMethodType(); 572 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0) 573 return true; 574 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0) 575 return true; 576 if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class) 577 return true; 578 return false; 579 } 580 /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) { 581 int refKind = getReferenceKind(); 582 if (refKind == originalRefKind) return true; 583 switch (originalRefKind) { 584 case REF_invokeInterface: 585 // Looking up an interface method, can get (e.g.) Object.hashCode 586 assert(refKind == REF_invokeVirtual || 587 refKind == REF_invokeSpecial) : this; 588 return true; 589 case REF_invokeVirtual: 590 case REF_newInvokeSpecial: 591 // Looked up a virtual, can get (e.g.) final String.hashCode. 592 assert(refKind == REF_invokeSpecial) : this; 593 return true; 594 } 595 assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind); 596 return true; 597 } 598 private boolean staticIsConsistent() { 599 byte refKind = getReferenceKind(); 600 return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0; 601 } 602 private boolean vminfoIsConsistent() { 603 byte refKind = getReferenceKind(); 604 assert(isResolved()); // else don't call 605 Object vminfo = MethodHandleNatives.getMemberVMInfo(this); 606 assert(vminfo instanceof Object[]); 607 long vmindex = (Long) ((Object[])vminfo)[0]; 608 Object vmtarget = ((Object[])vminfo)[1]; 609 if (MethodHandleNatives.refKindIsField(refKind)) { 610 assert(vmindex >= 0) : vmindex + ":" + this; 611 assert(vmtarget instanceof Class); 612 } else { 613 if (MethodHandleNatives.refKindDoesDispatch(refKind)) 614 assert(vmindex >= 0) : vmindex + ":" + this; 615 else 616 assert(vmindex < 0) : vmindex; 617 assert(vmtarget instanceof MemberName) : vmtarget + " in " + this; 618 } 619 return true; 620 } 621 622 private MemberName changeReferenceKind(byte refKind, byte oldKind) { 623 assert(getReferenceKind() == oldKind); 624 assert(MethodHandleNatives.refKindIsValid(refKind)); 625 flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); 626 return this; 627 } 628 629 private boolean testFlags(int mask, int value) { 630 return (flags & mask) == value; 631 } 632 private boolean testAllFlags(int mask) { 633 return testFlags(mask, mask); 634 } 635 private boolean testAnyFlags(int mask) { 636 return !testFlags(mask, 0); 637 } 638 639 /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). 640 * Also returns true for the non-public MH.invokeBasic. 641 */ 642 public boolean isMethodHandleInvoke() { 643 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; 644 final int negs = Modifier.STATIC; 645 if (testFlags(bits | negs, bits) && 646 clazz == MethodHandle.class) { 647 return isMethodHandleInvokeName(name); 648 } 649 return false; 650 } 651 public static boolean isMethodHandleInvokeName(String name) { 652 switch (name) { 653 case "invoke": 654 case "invokeExact": 655 case "invokeBasic": // internal sig-poly method 656 return true; 657 default: 658 return false; 659 } 660 } 661 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC; 662 663 /** Utility method to query the modifier flags of this member. */ 664 public boolean isStatic() { 665 return Modifier.isStatic(flags); 666 } 667 /** Utility method to query the modifier flags of this member. */ 668 public boolean isPublic() { 669 return Modifier.isPublic(flags); 670 } 671 /** Utility method to query the modifier flags of this member. */ 672 public boolean isPrivate() { 673 return Modifier.isPrivate(flags); 674 } 675 /** Utility method to query the modifier flags of this member. */ 676 public boolean isProtected() { 677 return Modifier.isProtected(flags); 678 } 679 /** Utility method to query the modifier flags of this member. */ 680 public boolean isFinal() { 681 return Modifier.isFinal(flags); 682 } 683 /** Utility method to query whether this member or its defining class is final. */ 684 public boolean canBeStaticallyBound() { 685 return Modifier.isFinal(flags | clazz.getModifiers()); 686 } 687 /** Utility method to query the modifier flags of this member. */ 688 public boolean isVolatile() { 689 return Modifier.isVolatile(flags); 690 } 691 /** Utility method to query the modifier flags of this member. */ 692 public boolean isAbstract() { 693 return Modifier.isAbstract(flags); 694 } 695 /** Utility method to query the modifier flags of this member. */ 696 public boolean isNative() { 697 return Modifier.isNative(flags); 698 } 699 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo 700 701 // unofficial modifier flags, used by HotSpot: 702 static final int BRIDGE = 0x00000040; 703 static final int VARARGS = 0x00000080; 704 static final int SYNTHETIC = 0x00001000; 705 static final int ANNOTATION= 0x00002000; 706 static final int ENUM = 0x00004000; 707 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 708 public boolean isBridge() { 709 return testAllFlags(IS_METHOD | BRIDGE); 710 } 711 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 712 public boolean isVarargs() { 713 return testAllFlags(VARARGS) && isInvocable(); 714 } 715 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 716 @Override 717 public boolean isSynthetic() { 718 return testAllFlags(SYNTHETIC); 719 } 720 721 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular 722 723 // modifiers exported by the JVM: 724 static final int RECOGNIZED_MODIFIERS = 0xFFFF; 725 726 // private flags, not part of RECOGNIZED_MODIFIERS: 727 static final int 728 IS_METHOD = MN_IS_METHOD, // method (not constructor) 729 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor 730 IS_FIELD = MN_IS_FIELD, // field 731 IS_TYPE = MN_IS_TYPE, // nested type 732 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected 733 734 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; 735 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; 736 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; 737 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; 738 static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES; 739 740 /** Utility method to query whether this member is a method or constructor. */ 741 public boolean isInvocable() { 742 return testAnyFlags(IS_INVOCABLE); 743 } 744 /** Utility method to query whether this member is a method, constructor, or field. */ 745 public boolean isFieldOrMethod() { 746 return testAnyFlags(IS_FIELD_OR_METHOD); 747 } 748 /** Query whether this member is a method. */ 749 public boolean isMethod() { 750 return testAllFlags(IS_METHOD); 751 } 752 /** Query whether this member is a constructor. */ 753 public boolean isConstructor() { 754 return testAllFlags(IS_CONSTRUCTOR); 755 } 756 /** Query whether this member is a field. */ 757 public boolean isField() { 758 return testAllFlags(IS_FIELD); 759 } 760 /** Query whether this member is a type. */ 761 public boolean isType() { 762 return testAllFlags(IS_TYPE); 763 } 764 /** Utility method to query whether this member is neither public, private, nor protected. */ 765 public boolean isPackage() { 766 return !testAnyFlags(ALL_ACCESS); 767 } 768 /** Query whether this member has a CallerSensitive annotation. */ 769 public boolean isCallerSensitive() { 770 return testAllFlags(CALLER_SENSITIVE); 771 } 772 773 /** Utility method to query whether this member is accessible from a given lookup class. */ 774 public boolean isAccessibleFrom(Class<?> lookupClass) { 775 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, 776 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE); 777 } 778 779 /** 780 * Calls down to the VM to fill in the fields. This method is 781 * synchronized to avoid racing calls. 782 */ 783 private void expandFromVM() { 784 if (type != null) { 785 return; 786 } 787 if (!isResolved()) { 788 return; 789 } 790 MethodHandleNatives.expand(this); 791 } 792 793 // Capturing information from the Core Reflection API: 794 private static int flagsMods(int flags, int mods, byte refKind) { 795 assert((flags & RECOGNIZED_MODIFIERS) == 0); 796 assert((mods & ~RECOGNIZED_MODIFIERS) == 0); 797 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); 798 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); 799 } 800 801 802 803 public MemberName asSpecial() { 804 switch (getReferenceKind()) { 805 case REF_invokeSpecial: return this; 806 case REF_invokeVirtual: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeVirtual); 807 case REF_invokeInterface: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeInterface); 808 case REF_newInvokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_newInvokeSpecial); 809 } 810 throw new IllegalArgumentException(this.toString()); 811 } 812 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind. 813 * In that case it must already be REF_invokeSpecial. 814 */ 815 public MemberName asConstructor() { 816 switch (getReferenceKind()) { 817 case REF_invokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_newInvokeSpecial, REF_invokeSpecial); 818 case REF_newInvokeSpecial: return this; 819 } 820 throw new IllegalArgumentException(this.toString()); 821 } 822 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind 823 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface. 824 * The end result is to get a fully virtualized version of the MN. 825 * (Note that resolving in the JVM will sometimes devirtualize, changing 826 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface 827 * in some corner cases to either of the previous two; this transform 828 * undoes that change under the assumption that it occurred.) 829 */ 830 public MemberName asNormalOriginal() { 831 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual; 832 byte refKind = getReferenceKind(); 833 byte newRefKind = refKind; 834 MemberName result = this; 835 switch (refKind) { 836 case REF_invokeInterface: 837 case REF_invokeVirtual: 838 case REF_invokeSpecial: 839 newRefKind = normalVirtual; 840 break; 841 } 842 if (newRefKind == refKind) 843 return this; 844 result = cloneAndChangeReferenceKindAndIntern(newRefKind, refKind); 845 assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); 846 return result; 847 } 848 849 private MemberName cloneAndChangeReferenceKindAndIntern(byte refKind, byte oldKind) { 850 MemberName tmp0 = null; 851 while (tmp0 == null) { 852 int tx_token = internTxnToken(); 853 tmp0 = clone().changeReferenceKind(refKind, oldKind).intern(this, tx_token); 854 } 855 return tmp0; 856 } 857 858 public boolean isGetter() { 859 return MethodHandleNatives.refKindIsGetter(getReferenceKind()); 860 } 861 public boolean isSetter() { 862 return MethodHandleNatives.refKindIsSetter(getReferenceKind()); 863 } 864 public MemberName asSetter() { 865 byte refKind = getReferenceKind(); 866 assert(MethodHandleNatives.refKindIsGetter(refKind)); 867 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 868 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); 869 return cloneAndChangeReferenceKindAndIntern(setterRefKind, refKind); 870 } 871 /** 872 * Create a name for a signature-polymorphic invoker. 873 * This is a placeholder for a signature-polymorphic instance 874 * (of MH.invokeExact, etc.) that the JVM does not reify. 875 * See comments on {@link MethodHandleNatives#linkMethod}. 876 */ 877 static MemberName makeMethodHandleInvoke(String name, MethodType type) { 878 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC); 879 } 880 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) { 881 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual); 882 mem.flags |= mods; // it's not resolved, but add these modifiers anyway 883 assert(mem.isMethodHandleInvoke()) : mem; 884 return mem; 885 } 886 887 // locally useful cloner 888 @Override protected MemberName clone() { 889 try { 890 return (MemberName) super.clone(); 891 } catch (CloneNotSupportedException ex) { 892 throw newInternalError(ex); 893 } 894 } 895 896 /** Get the definition of this member name. 897 * This may be in a super-class of the declaring class of this member. 898 */ 899 public MemberName getDefinition() { 900 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this); 901 if (isType()) return this; 902 MemberName res = this.clone(); 903 res.clazz = null; 904 res.type = null; 905 res.name = null; 906 res.resolution = res; 907 res.expandFromVM(); 908 assert(res.getName().equals(this.getName())); 909 return res; 910 } 911 912 @Override 913 public int hashCode() { 914 return Objects.hash(clazz, getReferenceKind(), name, getType()); 915 } 916 @Override 917 public boolean equals(Object that) { 918 return (that instanceof MemberName && this.equals((MemberName)that)); 919 } 920 921 /** Decide if two member names have exactly the same symbolic content. 922 * Does not take into account any actual class members, so even if 923 * two member names resolve to the same actual member, they may 924 * be distinct references. 925 */ 926 public boolean equals(MemberName that) { 927 if (this == that) return true; 928 if (that == null) return false; 929 return this.clazz == that.clazz 930 && this.getReferenceKind() == that.getReferenceKind() 931 && Objects.equals(this.name, that.name) 932 && Objects.equals(this.getType(), that.getType()); 933 } 934 935 @Override 936 public int compareTo(Object o) { 937 MemberName that = (MemberName) o; 938 939 /* First test equals. This make the ordering checks easier because we 940 * don't have to be precise and can use hash codes. 941 */ 942 if (equals(that)) { 943 return 0; 944 } 945 946 int diff = Integer.compare(this.name.hashCode(), that.name.hashCode()); 947 if (diff != 0) { 948 return diff; 949 } 950 951 diff = this.getReferenceKind() - that.getReferenceKind(); 952 if (diff != 0) { 953 return diff; 954 } 955 956 diff = Integer.compare(this.getType().hashCode(), that.getType().hashCode()); 957 if (diff != 0) { 958 return diff; 959 } 960 961 // Hashcodes apparently collided, try more detail. 962 diff = this.name.compareTo(that.name); 963 if (diff != 0) { 964 return diff; 965 } 966 967 // The classes ought to all be equal anyway in the usual use of 968 // compareTo, so check these later, 969 // but before comparing getType.toString(). 970 diff = Integer.compare(this.clazz.hashCode(),that.clazz.hashCode()); 971 if (diff != 0) { 972 return diff; 973 } 974 975 diff = this.getType().toString().compareTo(that.getType().toString()); 976 if (diff != 0) { 977 return diff; 978 } 979 980 diff = this.clazz.getName().compareTo(that.clazz.getName()); 981 if (diff != 0) { 982 return diff; 983 } 984 985 ClassLoader thisCl = this.clazz.getClassLoader(); 986 ClassLoader thatCl = that.clazz.getClassLoader(); 987 988 if (thisCl == thatCl) return 0; 989 990 diff = Integer.compare(thisCl == null ? 0 : thisCl.hashCode(), 991 thatCl == null ? 0 : thatCl.hashCode()); 992 993 return diff; 994 } 995 996 /** Query whether this member name is resolved to a non-static, non-final method. 997 */ 998 public boolean hasReceiverTypeDispatch() { 999 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); 1000 } 1001 1002 /** Query whether this member name is resolved. 1003 * A resolved member name is one for which the JVM has found 1004 * a method, constructor, field, or type binding corresponding exactly to the name. 1005 * (Document?) 1006 */ 1007 public boolean isResolved() { 1008 return resolution == null; 1009 } 1010 1011 void checkForTypeAlias() { 1012 if (isInvocable()) { 1013 MethodType type; 1014 if (this.type instanceof MethodType) 1015 type = (MethodType) this.type; 1016 else 1017 this.type = type = getMethodType(); 1018 if (type.erase() == type) return; 1019 if (VerifyAccess.isTypeVisible(type, clazz)) return; 1020 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); 1021 } else { 1022 Class<?> type; 1023 if (this.type instanceof Class<?>) 1024 type = (Class<?>) this.type; 1025 else 1026 this.type = type = getFieldType(); 1027 if (VerifyAccess.isTypeVisible(type, clazz)) return; 1028 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); 1029 } 1030 } 1031 1032 1033 /** Produce a string form of this member name. 1034 * For types, it is simply the type's own string (as reported by {@code toString}). 1035 * For fields, it is {@code "DeclaringClass.name/type"}. 1036 * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}. 1037 * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted. 1038 * If the member is unresolved, a prefix {@code "*."} is prepended. 1039 */ 1040 @SuppressWarnings("LocalVariableHidesMemberVariable") 1041 @Override 1042 public String toString() { 1043 if (isType()) 1044 return type.toString(); // class java.lang.String 1045 // else it is a field, method, or constructor 1046 StringBuilder buf = new StringBuilder(); 1047 if (getDeclaringClass() != null) { 1048 buf.append(getName(clazz)); 1049 buf.append('.'); 1050 } 1051 String name = getName(); 1052 buf.append(name == null ? "*" : name); 1053 Object type = getType(); 1054 if (!isInvocable()) { 1055 buf.append('/'); 1056 buf.append(type == null ? "*" : getName(type)); 1057 } else { 1058 buf.append(type == null ? "(*)*" : getName(type)); 1059 } 1060 byte refKind = getReferenceKind(); 1061 if (refKind != REF_NONE) { 1062 buf.append('/'); 1063 buf.append(MethodHandleNatives.refKindName(refKind)); 1064 } 1065 //buf.append("#").append(System.identityHashCode(this)); 1066 return buf.toString(); 1067 } 1068 private static String getName(Object obj) { 1069 if (obj instanceof Class<?>) 1070 return ((Class<?>)obj).getName(); 1071 return String.valueOf(obj); 1072 } 1073 1074 public IllegalAccessException makeAccessException(String message, Object from) { 1075 message = message + ": "+ toString(); 1076 if (from != null) message += ", from " + from; 1077 return new IllegalAccessException(message); 1078 } 1079 private String message() { 1080 if (isResolved()) 1081 return "no access"; 1082 else if (isConstructor()) 1083 return "no such constructor"; 1084 else if (isMethod()) 1085 return "no such method"; 1086 else 1087 return "no such field"; 1088 } 1089 public ReflectiveOperationException makeAccessException() { 1090 String message = message() + ": "+ toString(); 1091 ReflectiveOperationException ex; 1092 if (isResolved() || !(resolution instanceof NoSuchMethodError || 1093 resolution instanceof NoSuchFieldError)) 1094 ex = new IllegalAccessException(message); 1095 else if (isConstructor()) 1096 ex = new NoSuchMethodException(message); 1097 else if (isMethod()) 1098 ex = new NoSuchMethodException(message); 1099 else 1100 ex = new NoSuchFieldException(message); 1101 if (resolution instanceof Throwable) 1102 ex.initCause((Throwable) resolution); 1103 return ex; 1104 } 1105 1106 /** Actually making a query requires an access check. */ 1107 /*non-public*/ static Factory getFactory() { 1108 return Factory.INSTANCE; 1109 } 1110 /** A factory type for resolving member names with the help of the VM. 1111 * TBD: Define access-safe public constructors for this factory. 1112 */ 1113 /*non-public*/ static class Factory { 1114 private Factory() { } // singleton pattern 1115 static Factory INSTANCE = new Factory(); 1116 1117 private final static int ALLOWED_FLAGS = ALL_KINDS; 1118 1119 /// Queries 1120 List<MemberName> getMembers(Class<?> defc, 1121 String matchName, Object matchType, 1122 int matchFlags, Class<?> lookupClass) { 1123 matchFlags &= ALLOWED_FLAGS; 1124 String matchSig = null; 1125 if (matchType != null) { 1126 matchSig = BytecodeDescriptor.unparse(matchType); 1127 if (matchSig.startsWith("(")) 1128 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); 1129 else 1130 matchFlags &= ~(ALL_KINDS & ~IS_FIELD); 1131 } 1132 final int BUF_MAX = 0x2000; 1133 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1; 1134 MemberName[] buf = newMemberBuffer(len1); 1135 int totalCount = 0; 1136 ArrayList<MemberName[]> bufs = null; 1137 int bufCount = 0; 1138 for (;;) { 1139 bufCount = MethodHandleNatives.getMembers(defc, 1140 matchName, matchSig, matchFlags, 1141 lookupClass, 1142 totalCount, buf); 1143 if (bufCount <= buf.length) { 1144 if (bufCount < 0) bufCount = 0; 1145 totalCount += bufCount; 1146 break; 1147 } 1148 // JVM returned to us with an intentional overflow! 1149 totalCount += buf.length; 1150 int excess = bufCount - buf.length; 1151 if (bufs == null) bufs = new ArrayList<>(1); 1152 bufs.add(buf); 1153 int len2 = buf.length; 1154 len2 = Math.max(len2, excess); 1155 len2 = Math.max(len2, totalCount / 4); 1156 buf = newMemberBuffer(Math.min(BUF_MAX, len2)); 1157 } 1158 ArrayList<MemberName> result = new ArrayList<>(totalCount); 1159 if (bufs != null) { 1160 for (MemberName[] buf0 : bufs) { 1161 Collections.addAll(result, buf0); 1162 } 1163 } 1164 result.addAll(Arrays.asList(buf).subList(0, bufCount)); 1165 // Signature matching is not the same as type matching, since 1166 // one signature might correspond to several types. 1167 // So if matchType is a Class or MethodType, refilter the results. 1168 if (matchType != null && matchType != matchSig) { 1169 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) { 1170 MemberName m = it.next(); 1171 if (!matchType.equals(m.getType())) 1172 it.remove(); 1173 } 1174 } 1175 return result; 1176 } 1177 /** Produce a resolved version of the given member. 1178 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1179 * Access checking is performed on behalf of the given {@code lookupClass}. 1180 * If lookup fails or access is not permitted, null is returned. 1181 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 1182 */ 1183 private static MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { 1184 MemberName m = ref.clone(); // JVM will side-effect the ref 1185 assert(refKind == m.getReferenceKind()); 1186 try { 1187 m = MethodHandleNatives.resolve(m, lookupClass); 1188 m.checkForTypeAlias(); 1189 m.resolution = null; 1190 } catch (LinkageError ex) { 1191 // JVM reports that the "bytecode behavior" would get an error 1192 assert(!m.isResolved()); 1193 m.resolution = ex; 1194 return m; 1195 } 1196 assert(m.referenceKindIsConsistent()); 1197 m.initResolved(true); 1198 assert(m.vminfoIsConsistent()); 1199 // m = m.intern(); // do not intern -- caller should intern instead. 1200 return m; 1201 } 1202 /** Produce a resolved version of the given member. 1203 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1204 * Access checking is performed on behalf of the given {@code lookupClass}. 1205 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown. 1206 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 1207 */ 1208 public 1209 <NoSuchMemberException extends ReflectiveOperationException> 1210 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, 1211 Class<NoSuchMemberException> nsmClass) 1212 throws IllegalAccessException, NoSuchMemberException { 1213 MemberName result = resolveOrNot(refKind, m, lookupClass); 1214 1215 if (result.isResolved()) { 1216 return result; 1217 } else { // not resolved, throw exception 1218 ReflectiveOperationException ex = result.makeAccessException(); 1219 if (ex instanceof IllegalAccessException) { 1220 throw (IllegalAccessException) ex; 1221 } 1222 throw nsmClass.cast(ex); 1223 } 1224 } 1225 /** Produce a resolved version of the given member. 1226 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1227 * Access checking is performed on behalf of the given {@code lookupClass}. 1228 * If lookup fails or access is not permitted, return null. 1229 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 1230 */ 1231 public 1232 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { 1233 MemberName result = resolveOrNot(refKind, m, lookupClass); 1234 return result.isResolved() ? result : null; 1235 } 1236 1237 private static 1238 MemberName resolveOrNot(byte refKind, MemberName m, Class<?> lookupClass) { 1239 MemberName result = null; 1240 Class tx_class = m.getClass(); 1241 while (result == null) { // iterate till no race. 1242 int txn_token = internTxnToken(tx_class); 1243 1244 MemberName result0 = resolve(refKind, m, lookupClass); 1245 1246 if (result0.isResolved()) { 1247 if (result0.getClass() != tx_class) { 1248 Class prev_tx_class = tx_class; 1249 int prev_txn_token = txn_token; 1250 tx_class = result0.getClass(); 1251 txn_token = internTxnToken(tx_class); 1252 // Zero is a special case. 1253 if (txn_token != 0 || 1254 prev_txn_token != internTxnToken(prev_tx_class)) { 1255 // Resolved class is different and at least one 1256 // redef of it occurred, therefore repeat with 1257 // proper class for race consistency checking. 1258 continue; 1259 } 1260 } 1261 result = result0.intern(txn_token); 1262 } else { 1263 return result0; 1264 } 1265 } 1266 return result; 1267 } 1268 1269 /** Return a list of all methods defined by the given class. 1270 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1271 * Access checking is performed on behalf of the given {@code lookupClass}. 1272 * Inaccessible members are not added to the last. 1273 */ 1274 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 1275 Class<?> lookupClass) { 1276 return getMethods(defc, searchSupers, null, null, lookupClass); 1277 } 1278 /** Return a list of matching methods defined by the given class. 1279 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1280 * Returned methods will match the name (if not null) and the type (if not null). 1281 * Access checking is performed on behalf of the given {@code lookupClass}. 1282 * Inaccessible members are not added to the last. 1283 */ 1284 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 1285 String name, MethodType type, Class<?> lookupClass) { 1286 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1287 return getMembers(defc, name, type, matchFlags, lookupClass); 1288 } 1289 /** Return a list of all constructors defined by the given class. 1290 * Access checking is performed on behalf of the given {@code lookupClass}. 1291 * Inaccessible members are not added to the last. 1292 */ 1293 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) { 1294 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); 1295 } 1296 /** Return a list of all fields defined by the given class. 1297 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1298 * Access checking is performed on behalf of the given {@code lookupClass}. 1299 * Inaccessible members are not added to the last. 1300 */ 1301 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 1302 Class<?> lookupClass) { 1303 return getFields(defc, searchSupers, null, null, lookupClass); 1304 } 1305 /** Return a list of all fields defined by the given class. 1306 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1307 * Returned fields will match the name (if not null) and the type (if not null). 1308 * Access checking is performed on behalf of the given {@code lookupClass}. 1309 * Inaccessible members are not added to the last. 1310 */ 1311 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 1312 String name, Class<?> type, Class<?> lookupClass) { 1313 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1314 return getMembers(defc, name, type, matchFlags, lookupClass); 1315 } 1316 /** Return a list of all nested types defined by the given class. 1317 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1318 * Access checking is performed on behalf of the given {@code lookupClass}. 1319 * Inaccessible members are not added to the last. 1320 */ 1321 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers, 1322 Class<?> lookupClass) { 1323 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1324 return getMembers(defc, null, null, matchFlags, lookupClass); 1325 } 1326 private static MemberName[] newMemberBuffer(int length) { 1327 MemberName[] buf = new MemberName[length]; 1328 // fill the buffer with dummy structs for the JVM to fill in 1329 for (int i = 0; i < length; i++) 1330 buf[i] = new MemberName(); 1331 return buf; 1332 } 1333 } 1334 }