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