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 import sun.misc.Unsafe; 48 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 * <p> 60 * Whether resolved or not, a member name provides no access rights or 61 * invocation capability to its possessor. It is merely a compact 62 * representation of all symbolic information necessary to link to 63 * and properly use the named member. 64 * <p> 65 * When resolved, a member name's internal implementation may include references to JVM metadata. 66 * This representation is stateless and only descriptive. 67 * It provides no private information and no capability to use the member. 68 * Resolved MemberNames are always interned (except for Class MemberNames) 69 * which allows updating when classes are redefined. 70 * <p> 71 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information 72 * about the internals of a method (except its bytecodes) and also 73 * allows invocation. A MemberName is much lighter than a Method, 74 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), 75 * and those seven fields omit much of the information in Method. 76 * @author jrose 77 */ 78 /*non-public*/ final class MemberName implements Member, 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 private MemberName next; // used for a linked list of MemberNames known to VM 84 //@Injected JVM_Method* vmtarget; 85 //@Injected int vmindex; 86 private Object resolution; // if null, this guy is resolved 87 88 private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 89 90 // bare-bones constructor; the JVM will fill it in 91 MemberName() { } 92 93 /** Create a name for the given class. The resulting name will be in a resolved state. */ 94 public MemberName(Class<?> type) { 95 init(type.getDeclaringClass(), type.getSimpleName(), type, 96 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); 97 initResolved(true); 98 } 99 100 // Construction from symbolic parts, for queries: 101 /** Create a field or type name from the given components: 102 * Declaring class, name, type, reference kind. 103 * The declaring class may be supplied as null if this is to be a bare name and type. 104 * The resulting name will in an unresolved state. 105 */ 106 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { 107 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); 108 initResolved(false); 109 } 110 111 /** Create a field or type name from the given components: Declaring class, name, type. 112 * The declaring class may be supplied as null if this is to be a bare name and type. 113 * The modifier flags default to zero. 114 * The resulting name will in an unresolved state. 115 */ 116 public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) { 117 this(defClass, name, type, REF_NONE); 118 initResolved(false); 119 } 120 121 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. 122 * It will be a constructor if and only if the name is {@code "<init>"}. 123 * The declaring class may be supplied as null if this is to be a bare name and type. 124 * The last argument is optional, a boolean which requests REF_invokeSpecial. 125 * The resulting name will in an unresolved state. 126 */ 127 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { 128 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); 129 init(defClass, name, type, flagsMods(initFlags, 0, refKind)); 130 initResolved(false); 131 } 132 133 /** Create a method, constructor, or field name from the given components: 134 * Reference kind, declaring class, name, type. 135 */ 136 public MemberName(byte refKind, Class<?> defClass, String name, Object type) { 137 int kindFlags; 138 if (MethodHandleNatives.refKindIsField(refKind)) { 139 kindFlags = IS_FIELD; 140 if (!(type instanceof Class)) 141 throw newIllegalArgumentException("not a field type"); 142 } else if (MethodHandleNatives.refKindIsMethod(refKind)) { 143 kindFlags = IS_METHOD; 144 if (!(type instanceof MethodType)) 145 throw newIllegalArgumentException("not a method type"); 146 } else if (refKind == REF_newInvokeSpecial) { 147 kindFlags = IS_CONSTRUCTOR; 148 if (!(type instanceof MethodType) || 149 !CONSTRUCTOR_NAME.equals(name)) 150 throw newIllegalArgumentException("not a constructor type or name"); 151 } else { 152 throw newIllegalArgumentException("bad reference kind "+refKind); 153 } 154 init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); 155 initResolved(false); 156 } 157 158 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ 159 public static MemberName make(Method m) { 160 return make(m, false); 161 } 162 163 @SuppressWarnings("LeakingThisInConstructor") 164 private MemberName(Method m, boolean wantSpecial) { 165 m.getClass(); // NPE check 166 // fill in vmtarget, vmindex while we have m in hand: 167 MethodHandleNatives.init(this, m); 168 if (clazz == null) { // MHN.init failed 169 if (m.getDeclaringClass() == MethodHandle.class && 170 isMethodHandleInvokeName(m.getName())) { 171 // The JVM did not reify this signature-polymorphic instance. 172 // Need a special case here. 173 // See comments on MethodHandleNatives.linkMethod. 174 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); 175 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); 176 init(MethodHandle.class, m.getName(), type, flags); 177 if (isMethodHandleInvoke()) { 178 return; 179 } 180 } 181 throw new LinkageError(m.toString()); 182 } 183 assert(isResolved() && this.clazz != null); 184 this.name = m.getName(); 185 if (this.type == null) { 186 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; 187 } 188 if (wantSpecial) { 189 if (isAbstract()) { 190 throw new AbstractMethodError(this.toString()); 191 } 192 if (getReferenceKind() == REF_invokeVirtual) { 193 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); 194 } else if (getReferenceKind() == REF_invokeInterface) { 195 // invokeSpecial on a default method 196 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); 197 } 198 } 199 } 200 201 public static MemberName make(Method m, boolean wantSpecial) { 202 // Unreflected member names are resolved so intern them here. 203 MemberName tmp0 = null; 204 InternTransaction tx = new InternTransaction(m.getDeclaringClass()); 205 while (tmp0 == null) { 206 MemberName tmp = new MemberName(m, wantSpecial); 207 tmp0 = tx.tryIntern(tmp); 208 } 209 return tmp0; 210 } 211 212 @SuppressWarnings("LeakingThisInConstructor") 213 private MemberName(Constructor<?> ctor) { 214 ctor.getClass(); // NPE check 215 // fill in vmtarget, vmindex while we have ctor in hand: 216 MethodHandleNatives.init(this, ctor); 217 assert(isResolved() && this.clazz != null); 218 this.name = CONSTRUCTOR_NAME; 219 if (this.type == null) { 220 this.type = new Object[] { void.class, ctor.getParameterTypes() }; 221 } 222 } 223 224 /** 225 * Create a name for the given reflected constructor. 226 * The resulting name will be in a resolved state. 227 */ 228 public static MemberName make(Constructor<?> ctor) { 229 // Unreflected member names are resolved so intern them here. 230 MemberName tmp0 = null; 231 InternTransaction tx = new InternTransaction(ctor.getDeclaringClass()); 232 while (tmp0 == null) { 233 MemberName tmp = new MemberName(ctor); 234 tmp0 = tx.tryIntern(tmp); 235 } 236 return tmp0; 237 } 238 239 /** 240 * Create a name for the given reflected field. 241 * The resulting name will be in a resolved state. 242 */ 243 public static MemberName make(Field field) { 244 return make(field, false); 245 } 246 247 @SuppressWarnings("LeakingThisInConstructor") 248 private MemberName(Field field, boolean makeSetter) { 249 field.getClass(); // NPE check 250 // fill in vmtarget, vmindex while we have field in hand: 251 MethodHandleNatives.init(this, field); 252 assert(isResolved() && this.clazz != null); 253 this.name = field.getName(); 254 this.type = field.getType(); 255 byte refKind = this.getReferenceKind(); 256 assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); 257 if (makeSetter) { 258 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 259 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); 260 } 261 } 262 263 /** 264 * Create a name for the given reflected field, optionally making it a setter. 265 * The resulting name will be in a resolved state. 266 */ 267 public static MemberName make(Field field, boolean makeSetter) { 268 // Unreflected member names are resolved so intern them here. 269 MemberName tmp0 = null; 270 InternTransaction tx = new InternTransaction(field.getDeclaringClass()); 271 while (tmp0 == null) { 272 MemberName tmp = new MemberName(field, makeSetter); 273 tmp0 = tx.tryIntern(tmp); 274 } 275 return tmp0; 276 } 277 278 /** Initialize a query. It is not resolved. */ 279 private void init(Class<?> defClass, String name, Object type, int flags) { 280 // defining class is allowed to be null (for a naked name/type pair) 281 //name.toString(); // null check 282 //type.equals(type); // null check 283 // fill in fields: 284 this.clazz = defClass; 285 this.name = name; 286 this.type = type; 287 this.flags = flags; 288 assert(testAnyFlags(ALL_KINDS)); 289 assert(this.resolution == null); // nobody should have touched this yet 290 //assert(referenceKindIsConsistent()); // do this after resolution 291 } 292 293 private void initResolved(boolean isResolved) { 294 assert(this.resolution == null); // not initialized yet! 295 if (!isResolved) 296 this.resolution = this; 297 assert(isResolved() == isResolved); 298 } 299 300 /** 301 * Helper method to intern this member name in the declaring class' member name table. 302 */ 303 @SuppressWarnings("unchecked") 304 private MemberName intern(int transaction_token) { 305 return internMemberName(clazz, this, transaction_token); 306 } 307 308 /** 309 * Helper method to obtain the transaction token for interning, given Class clazz. 310 * @param clazz 311 * @return transaction token (class redefinition count) 312 */ 313 static private int internTxnToken(Class clazz) { 314 return clazz == null ? 0 : jla.getClassRedefinedCount(clazz); 315 } 316 317 /** 318 * Helper method to obtain the transaction token for interning, given this. 319 * @return 320 */ 321 private int internTxnToken() { 322 return internTxnToken(clazz); 323 } 324 325 /** 326 * Helper method to conditionally intern cloned+modified member names. 327 */ 328 private MemberName intern(MemberName likeThis, int transaction_token) { 329 if (likeThis.isResolved()) 330 return intern(transaction_token); 331 else 332 return this; 333 } 334 335 /** 336 * Helper class to handle the case where the class checked for no 337 * redefinition may not be correct; resolution can end up with a different 338 * class. 339 */ 340 static class InternTransaction { 341 Class<?> tx_class; 342 int txn_token; 343 344 InternTransaction(Class<?> tx_class) { 345 this.tx_class = tx_class; 346 this.txn_token = internTxnToken(tx_class); 347 } 348 349 /** 350 * If member_name is not resolved, returns member_name; if is resolved, 351 * attempts to intern member_name (once) while checking for races. 352 * 353 * @param member_name 354 * @return member_name if not resolved, null if racing, otherwise 355 * value of interned member_name. 356 */ 357 MemberName tryIntern(MemberName member_name) { 358 if (member_name.isResolved()) { 359 if (member_name.clazz != tx_class) { 360 Class prev_tx_class = tx_class; 361 int prev_txn_token = txn_token; 362 tx_class = member_name.clazz; 363 txn_token = internTxnToken(tx_class); 364 // Zero is a special case. 365 if (txn_token != 0 || 366 prev_txn_token != internTxnToken(prev_tx_class)) { 367 // Resolved class is different and at least one 368 // redef of it occurred, therefore repeat with 369 // proper class for race consistency checking. 370 return null; 371 } 372 } 373 member_name = member_name.intern(txn_token); 374 if (member_name == null) { 375 // Update the token for the next try. 376 txn_token = internTxnToken(tx_class); 377 } 378 } 379 return member_name; 380 } 381 } 382 383 /** Return the declaring class of this member. 384 * In the case of a bare name and type, the declaring class will be null. 385 */ 386 @Override 387 public Class<?> getDeclaringClass() { 388 return clazz; 389 } 390 391 /** Utility method producing the class loader of the declaring class. */ 392 public ClassLoader getClassLoader() { 393 return clazz.getClassLoader(); 394 } 395 396 /** Return the simple name of this member. 397 * For a type, it is the same as {@link Class#getSimpleName}. 398 * For a method or field, it is the simple name of the member. 399 * For a constructor, it is always {@code "<init>"}. 400 */ 401 @Override 402 public String getName() { 403 if (name == null) { 404 expandFromVM(); 405 if (name == null) { 406 return null; 407 } 408 } 409 return name; 410 } 411 412 public MethodType getMethodOrFieldType() { 413 if (isInvocable()) 414 return getMethodType(); 415 if (isGetter()) 416 return MethodType.methodType(getFieldType()); 417 if (isSetter()) 418 return MethodType.methodType(void.class, getFieldType()); 419 throw new InternalError("not a method or field: "+this); 420 } 421 422 /** Return the declared type of this member, which 423 * must be a method or constructor. 424 */ 425 public MethodType getMethodType() { 426 if (type == null) { 427 expandFromVM(); 428 if (type == null) { 429 return null; 430 } 431 } 432 if (!isInvocable()) { 433 throw newIllegalArgumentException("not invocable, no method type"); 434 } 435 436 { 437 // Get a snapshot of type which doesn't get changed by racing threads. 438 final Object type = this.type; 439 if (type instanceof MethodType) { 440 return (MethodType) type; 441 } 442 } 443 444 // type is not a MethodType yet. Convert it thread-safely. 445 synchronized (this) { 446 if (type instanceof String) { 447 String sig = (String) type; 448 MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader()); 449 type = res; 450 } else if (type instanceof Object[]) { 451 Object[] typeInfo = (Object[]) type; 452 Class<?>[] ptypes = (Class<?>[]) typeInfo[1]; 453 Class<?> rtype = (Class<?>) typeInfo[0]; 454 MethodType res = MethodType.methodType(rtype, ptypes); 455 type = res; 456 } 457 // Make sure type is a MethodType for racing threads. 458 assert type instanceof MethodType : "bad method type " + type; 459 } 460 return (MethodType) type; 461 } 462 463 /** Return the actual type under which this method or constructor must be invoked. 464 * For non-static methods or constructors, this is the type with a leading parameter, 465 * a reference to declaring class. For static methods, it is the same as the declared type. 466 */ 467 public MethodType getInvocationType() { 468 MethodType itype = getMethodOrFieldType(); 469 if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial) 470 return itype.changeReturnType(clazz); 471 if (!isStatic()) 472 return itype.insertParameterTypes(0, clazz); 473 return itype; 474 } 475 476 /** Utility method producing the parameter types of the method type. */ 477 public Class<?>[] getParameterTypes() { 478 return getMethodType().parameterArray(); 479 } 480 481 /** Utility method producing the return type of the method type. */ 482 public Class<?> getReturnType() { 483 return getMethodType().returnType(); 484 } 485 486 /** Return the declared type of this member, which 487 * must be a field or type. 488 * If it is a type member, that type itself is returned. 489 */ 490 public Class<?> getFieldType() { 491 if (type == null) { 492 expandFromVM(); 493 if (type == null) { 494 return null; 495 } 496 } 497 if (isInvocable()) { 498 throw newIllegalArgumentException("not a field or nested class, no simple type"); 499 } 500 501 { 502 // Get a snapshot of type which doesn't get changed by racing threads. 503 final Object type = this.type; 504 if (type instanceof Class<?>) { 505 return (Class<?>) type; 506 } 507 } 508 509 // type is not a Class yet. Convert it thread-safely. 510 synchronized (this) { 511 if (type instanceof String) { 512 String sig = (String) type; 513 MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader()); 514 Class<?> res = mtype.returnType(); 515 type = res; 516 } 517 // Make sure type is a Class for racing threads. 518 assert type instanceof Class<?> : "bad field type " + type; 519 } 520 return (Class<?>) type; 521 } 522 523 /** Utility method to produce either the method type or field type of this member. */ 524 public Object getType() { 525 return (isInvocable() ? getMethodType() : getFieldType()); 526 } 527 528 /** Utility method to produce the signature of this member, 529 * used within the class file format to describe its type. 530 */ 531 public String getSignature() { 532 if (type == null) { 533 expandFromVM(); 534 if (type == null) { 535 return null; 536 } 537 } 538 if (isInvocable()) 539 return BytecodeDescriptor.unparse(getMethodType()); 540 else 541 return BytecodeDescriptor.unparse(getFieldType()); 542 } 543 544 /** Return the modifier flags of this member. 545 * @see java.lang.reflect.Modifier 546 */ 547 @Override 548 public int getModifiers() { 549 return (flags & RECOGNIZED_MODIFIERS); 550 } 551 552 /** Return the reference kind of this member, or zero if none. 553 */ 554 public byte getReferenceKind() { 555 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK); 556 } 557 private boolean referenceKindIsConsistent() { 558 byte refKind = getReferenceKind(); 559 if (refKind == REF_NONE) return isType(); 560 if (isField()) { 561 assert(staticIsConsistent()); 562 assert(MethodHandleNatives.refKindIsField(refKind)); 563 } else if (isConstructor()) { 564 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial); 565 } else if (isMethod()) { 566 assert(staticIsConsistent()); 567 assert(MethodHandleNatives.refKindIsMethod(refKind)); 568 if (clazz.isInterface()) 569 assert(refKind == REF_invokeInterface || 570 refKind == REF_invokeStatic || 571 refKind == REF_invokeSpecial || 572 refKind == REF_invokeVirtual && isObjectPublicMethod()); 573 } else { 574 assert(false); 575 } 576 return true; 577 } 578 private boolean isObjectPublicMethod() { 579 if (clazz == Object.class) return true; 580 MethodType mtype = getMethodType(); 581 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0) 582 return true; 583 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0) 584 return true; 585 if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class) 586 return true; 587 return false; 588 } 589 /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) { 590 int refKind = getReferenceKind(); 591 if (refKind == originalRefKind) return true; 592 switch (originalRefKind) { 593 case REF_invokeInterface: 594 // Looking up an interface method, can get (e.g.) Object.hashCode 595 assert(refKind == REF_invokeVirtual || 596 refKind == REF_invokeSpecial) : this; 597 return true; 598 case REF_invokeVirtual: 599 case REF_newInvokeSpecial: 600 // Looked up a virtual, can get (e.g.) final String.hashCode. 601 assert(refKind == REF_invokeSpecial) : this; 602 return true; 603 } 604 assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind); 605 return true; 606 } 607 private boolean staticIsConsistent() { 608 byte refKind = getReferenceKind(); 609 return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0; 610 } 611 private boolean vminfoIsConsistent() { 612 byte refKind = getReferenceKind(); 613 assert(isResolved()); // else don't call 614 Object vminfo = MethodHandleNatives.getMemberVMInfo(this); 615 assert(vminfo instanceof Object[]); 616 long vmindex = (Long) ((Object[])vminfo)[0]; 617 Object vmtarget = ((Object[])vminfo)[1]; 618 if (MethodHandleNatives.refKindIsField(refKind)) { 619 assert(vmindex >= 0) : vmindex + ":" + this; 620 assert(vmtarget instanceof Class); 621 } else { 622 if (MethodHandleNatives.refKindDoesDispatch(refKind)) 623 assert(vmindex >= 0) : vmindex + ":" + this; 624 else 625 assert(vmindex < 0) : vmindex; 626 assert(vmtarget instanceof MemberName) : vmtarget + " in " + this; 627 } 628 return true; 629 } 630 631 private MemberName changeReferenceKind(byte refKind, byte oldKind) { 632 assert(getReferenceKind() == oldKind); 633 assert(MethodHandleNatives.refKindIsValid(refKind)); 634 flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); 635 return this; 636 } 637 638 private boolean testFlags(int mask, int value) { 639 return (flags & mask) == value; 640 } 641 private boolean testAllFlags(int mask) { 642 return testFlags(mask, mask); 643 } 644 private boolean testAnyFlags(int mask) { 645 return !testFlags(mask, 0); 646 } 647 648 /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). 649 * Also returns true for the non-public MH.invokeBasic. 650 */ 651 public boolean isMethodHandleInvoke() { 652 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; 653 final int negs = Modifier.STATIC; 654 if (testFlags(bits | negs, bits) && 655 clazz == MethodHandle.class) { 656 return isMethodHandleInvokeName(name); 657 } 658 return false; 659 } 660 public static boolean isMethodHandleInvokeName(String name) { 661 switch (name) { 662 case "invoke": 663 case "invokeExact": 664 case "invokeBasic": // internal sig-poly method 665 return true; 666 default: 667 return false; 668 } 669 } 670 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC; 671 672 /** Utility method to query the modifier flags of this member. */ 673 public boolean isStatic() { 674 return Modifier.isStatic(flags); 675 } 676 /** Utility method to query the modifier flags of this member. */ 677 public boolean isPublic() { 678 return Modifier.isPublic(flags); 679 } 680 /** Utility method to query the modifier flags of this member. */ 681 public boolean isPrivate() { 682 return Modifier.isPrivate(flags); 683 } 684 /** Utility method to query the modifier flags of this member. */ 685 public boolean isProtected() { 686 return Modifier.isProtected(flags); 687 } 688 /** Utility method to query the modifier flags of this member. */ 689 public boolean isFinal() { 690 return Modifier.isFinal(flags); 691 } 692 /** Utility method to query whether this member or its defining class is final. */ 693 public boolean canBeStaticallyBound() { 694 return Modifier.isFinal(flags | clazz.getModifiers()); 695 } 696 /** Utility method to query the modifier flags of this member. */ 697 public boolean isVolatile() { 698 return Modifier.isVolatile(flags); 699 } 700 /** Utility method to query the modifier flags of this member. */ 701 public boolean isAbstract() { 702 return Modifier.isAbstract(flags); 703 } 704 /** Utility method to query the modifier flags of this member. */ 705 public boolean isNative() { 706 return Modifier.isNative(flags); 707 } 708 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo 709 710 // unofficial modifier flags, used by HotSpot: 711 static final int BRIDGE = 0x00000040; 712 static final int VARARGS = 0x00000080; 713 static final int SYNTHETIC = 0x00001000; 714 static final int ANNOTATION= 0x00002000; 715 static final int ENUM = 0x00004000; 716 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 717 public boolean isBridge() { 718 return testAllFlags(IS_METHOD | BRIDGE); 719 } 720 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 721 public boolean isVarargs() { 722 return testAllFlags(VARARGS) && isInvocable(); 723 } 724 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ 725 @Override 726 public boolean isSynthetic() { 727 return testAllFlags(SYNTHETIC); 728 } 729 730 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular 731 732 // modifiers exported by the JVM: 733 static final int RECOGNIZED_MODIFIERS = 0xFFFF; 734 735 // private flags, not part of RECOGNIZED_MODIFIERS: 736 static final int 737 IS_METHOD = MN_IS_METHOD, // method (not constructor) 738 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor 739 IS_FIELD = MN_IS_FIELD, // field 740 IS_TYPE = MN_IS_TYPE, // nested type 741 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected 742 743 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; 744 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; 745 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; 746 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; 747 static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES; 748 749 /** Utility method to query whether this member is a method or constructor. */ 750 public boolean isInvocable() { 751 return testAnyFlags(IS_INVOCABLE); 752 } 753 /** Utility method to query whether this member is a method, constructor, or field. */ 754 public boolean isFieldOrMethod() { 755 return testAnyFlags(IS_FIELD_OR_METHOD); 756 } 757 /** Query whether this member is a method. */ 758 public boolean isMethod() { 759 return testAllFlags(IS_METHOD); 760 } 761 /** Query whether this member is a constructor. */ 762 public boolean isConstructor() { 763 return testAllFlags(IS_CONSTRUCTOR); 764 } 765 /** Query whether this member is a field. */ 766 public boolean isField() { 767 return testAllFlags(IS_FIELD); 768 } 769 /** Query whether this member is a type. */ 770 public boolean isType() { 771 return testAllFlags(IS_TYPE); 772 } 773 /** Utility method to query whether this member is neither public, private, nor protected. */ 774 public boolean isPackage() { 775 return !testAnyFlags(ALL_ACCESS); 776 } 777 /** Query whether this member has a CallerSensitive annotation. */ 778 public boolean isCallerSensitive() { 779 return testAllFlags(CALLER_SENSITIVE); 780 } 781 782 /** Utility method to query whether this member is accessible from a given lookup class. */ 783 public boolean isAccessibleFrom(Class<?> lookupClass) { 784 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, 785 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE); 786 } 787 788 /** 789 * Calls down to the VM to fill in the fields. This method is 790 * synchronized to avoid racing calls. 791 */ 792 private void expandFromVM() { 793 if (type != null) { 794 return; 795 } 796 if (!isResolved()) { 797 return; 798 } 799 MethodHandleNatives.expand(this); 800 } 801 802 // Capturing information from the Core Reflection API: 803 private static int flagsMods(int flags, int mods, byte refKind) { 804 assert((flags & RECOGNIZED_MODIFIERS) == 0); 805 assert((mods & ~RECOGNIZED_MODIFIERS) == 0); 806 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); 807 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); 808 } 809 810 public MemberName asSpecial() { 811 switch (getReferenceKind()) { 812 case REF_invokeSpecial: return this; 813 case REF_invokeVirtual: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeVirtual); 814 case REF_invokeInterface: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeInterface); 815 case REF_newInvokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_newInvokeSpecial); 816 } 817 throw new IllegalArgumentException(this.toString()); 818 } 819 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind. 820 * In that case it must already be REF_invokeSpecial. 821 */ 822 public MemberName asConstructor() { 823 switch (getReferenceKind()) { 824 case REF_invokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_newInvokeSpecial, REF_invokeSpecial); 825 case REF_newInvokeSpecial: return this; 826 } 827 throw new IllegalArgumentException(this.toString()); 828 } 829 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind 830 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface. 831 * The end result is to get a fully virtualized version of the MN. 832 * (Note that resolving in the JVM will sometimes devirtualize, changing 833 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface 834 * in some corner cases to either of the previous two; this transform 835 * undoes that change under the assumption that it occurred.) 836 */ 837 public MemberName asNormalOriginal() { 838 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual; 839 byte refKind = getReferenceKind(); 840 byte newRefKind = refKind; 841 MemberName result = this; 842 switch (refKind) { 843 case REF_invokeInterface: 844 case REF_invokeVirtual: 845 case REF_invokeSpecial: 846 newRefKind = normalVirtual; 847 break; 848 } 849 if (newRefKind == refKind) 850 return this; 851 result = cloneAndChangeReferenceKindAndIntern(newRefKind, refKind); 852 assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); 853 return result; 854 } 855 856 /** 857 * Clones, changes reference kind in the clone, and if this is resolved, 858 * also interns the result, repeating the intern operation till it succeeds. 859 * 860 * @param refKind 861 * @param oldKind 862 * @return 863 */ 864 private MemberName cloneAndChangeReferenceKindAndIntern(byte refKind, byte oldKind) { 865 MemberName tmp0 = null; 866 while (tmp0 == null) { 867 int tx_token = internTxnToken(); // this and clone will have same token 868 tmp0 = clone().changeReferenceKind(refKind, oldKind).intern(this, tx_token); 869 } 870 return tmp0; 871 } 872 873 public boolean isGetter() { 874 return MethodHandleNatives.refKindIsGetter(getReferenceKind()); 875 } 876 public boolean isSetter() { 877 return MethodHandleNatives.refKindIsSetter(getReferenceKind()); 878 } 879 public MemberName asSetter() { 880 byte refKind = getReferenceKind(); 881 assert(MethodHandleNatives.refKindIsGetter(refKind)); 882 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); 883 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); 884 return cloneAndChangeReferenceKindAndIntern(setterRefKind, refKind); 885 } 886 /** 887 * Create a name for a signature-polymorphic invoker. 888 * This is a placeholder for a signature-polymorphic instance 889 * (of MH.invokeExact, etc.) that the JVM does not reify. 890 * The returned MemberName is not resolved. 891 * See comments on {@link MethodHandleNatives#linkMethod}. 892 */ 893 static MemberName makeMethodHandleInvoke(String name, MethodType type) { 894 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC); 895 } 896 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) { 897 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual); 898 mem.flags |= mods; // it's not resolved, but add these modifiers anyway 899 assert(mem.isMethodHandleInvoke()) : mem; 900 return mem; 901 } 902 903 // locally useful cloner 904 @Override protected MemberName clone() { 905 try { 906 return (MemberName) super.clone(); 907 } catch (CloneNotSupportedException ex) { 908 throw newInternalError(ex); 909 } 910 } 911 912 /** Get the definition of this member name. 913 * This may be in a super-class of the declaring class of this member. 914 */ 915 public MemberName getDefinition() { 916 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this); 917 if (isType()) return this; 918 MemberName res = this.clone(); 919 res.clazz = null; 920 res.type = null; 921 res.name = null; 922 res.resolution = res; 923 res.expandFromVM(); 924 assert(res.getName().equals(this.getName())); 925 return res; 926 } 927 928 @Override 929 public int hashCode() { 930 return Objects.hash(clazz, getReferenceKind(), name, getType()); 931 } 932 @Override 933 public boolean equals(Object that) { 934 return (that instanceof MemberName && this.equals((MemberName)that)); 935 } 936 937 /** Decide if two member names have exactly the same symbolic content. 938 * Does not take into account any actual class members, so even if 939 * two member names resolve to the same actual member, they may 940 * be distinct references. 941 */ 942 public boolean equals(MemberName that) { 943 if (this == that) return true; 944 if (that == null) return false; 945 return this.clazz == that.clazz 946 && this.getReferenceKind() == that.getReferenceKind() 947 && Objects.equals(this.name, that.name) 948 && Objects.equals(this.getType(), that.getType()); 949 } 950 951 /** Query whether this member name is resolved to a non-static, non-final method. 952 */ 953 public boolean hasReceiverTypeDispatch() { 954 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); 955 } 956 957 /** Query whether this member name is resolved. 958 * A resolved member name is one for which the JVM has found 959 * a method, constructor, field, or type binding corresponding exactly to the name. 960 * (Document?) 961 */ 962 public boolean isResolved() { 963 return resolution == null; 964 } 965 966 void checkForTypeAlias() { 967 if (isInvocable()) { 968 MethodType type; 969 if (this.type instanceof MethodType) 970 type = (MethodType) this.type; 971 else 972 this.type = type = getMethodType(); 973 if (type.erase() == type) return; 974 if (VerifyAccess.isTypeVisible(type, clazz)) return; 975 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); 976 } else { 977 Class<?> type; 978 if (this.type instanceof Class<?>) 979 type = (Class<?>) this.type; 980 else 981 this.type = type = getFieldType(); 982 if (VerifyAccess.isTypeVisible(type, clazz)) return; 983 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); 984 } 985 } 986 987 988 /** Produce a string form of this member name. 989 * For types, it is simply the type's own string (as reported by {@code toString}). 990 * For fields, it is {@code "DeclaringClass.name/type"}. 991 * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}. 992 * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted. 993 * If the member is unresolved, a prefix {@code "*."} is prepended. 994 */ 995 @SuppressWarnings("LocalVariableHidesMemberVariable") 996 @Override 997 public String toString() { 998 if (isType()) 999 return type.toString(); // class java.lang.String 1000 // else it is a field, method, or constructor 1001 StringBuilder buf = new StringBuilder(); 1002 if (getDeclaringClass() != null) { 1003 buf.append(getName(clazz)); 1004 buf.append('.'); 1005 } 1006 String name = getName(); 1007 buf.append(name == null ? "*" : name); 1008 Object type = getType(); 1009 if (!isInvocable()) { 1010 buf.append('/'); 1011 buf.append(type == null ? "*" : getName(type)); 1012 } else { 1013 buf.append(type == null ? "(*)*" : getName(type)); 1014 } 1015 byte refKind = getReferenceKind(); 1016 if (refKind != REF_NONE) { 1017 buf.append('/'); 1018 buf.append(MethodHandleNatives.refKindName(refKind)); 1019 } 1020 //buf.append("#").append(System.identityHashCode(this)); 1021 return buf.toString(); 1022 } 1023 private static String getName(Object obj) { 1024 if (obj instanceof Class<?>) 1025 return ((Class<?>)obj).getName(); 1026 return String.valueOf(obj); 1027 } 1028 1029 public IllegalAccessException makeAccessException(String message, Object from) { 1030 message = message + ": "+ toString(); 1031 if (from != null) message += ", from " + from; 1032 return new IllegalAccessException(message); 1033 } 1034 private String message() { 1035 if (isResolved()) 1036 return "no access"; 1037 else if (isConstructor()) 1038 return "no such constructor"; 1039 else if (isMethod()) 1040 return "no such method"; 1041 else 1042 return "no such field"; 1043 } 1044 public ReflectiveOperationException makeAccessException() { 1045 String message = message() + ": "+ toString(); 1046 ReflectiveOperationException ex; 1047 if (isResolved() || !(resolution instanceof NoSuchMethodError || 1048 resolution instanceof NoSuchFieldError)) 1049 ex = new IllegalAccessException(message); 1050 else if (isConstructor()) 1051 ex = new NoSuchMethodException(message); 1052 else if (isMethod()) 1053 ex = new NoSuchMethodException(message); 1054 else 1055 ex = new NoSuchFieldException(message); 1056 if (resolution instanceof Throwable) 1057 ex.initCause((Throwable) resolution); 1058 return ex; 1059 } 1060 1061 /** Actually making a query requires an access check. */ 1062 /*non-public*/ static Factory getFactory() { 1063 return Factory.INSTANCE; 1064 } 1065 /** A factory type for resolving member names with the help of the VM. 1066 * TBD: Define access-safe public constructors for this factory. 1067 */ 1068 /*non-public*/ static class Factory { 1069 private Factory() { } // singleton pattern 1070 static Factory INSTANCE = new Factory(); 1071 1072 private final static int ALLOWED_FLAGS = ALL_KINDS; 1073 1074 /// Queries 1075 List<MemberName> getMembers(Class<?> defc, 1076 String matchName, Object matchType, 1077 int matchFlags, Class<?> lookupClass) { 1078 matchFlags &= ALLOWED_FLAGS; 1079 String matchSig = null; 1080 if (matchType != null) { 1081 matchSig = BytecodeDescriptor.unparse(matchType); 1082 if (matchSig.startsWith("(")) 1083 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); 1084 else 1085 matchFlags &= ~(ALL_KINDS & ~IS_FIELD); 1086 } 1087 final int BUF_MAX = 0x2000; 1088 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1; 1089 MemberName[] buf = newMemberBuffer(len1); 1090 int totalCount = 0; 1091 ArrayList<MemberName[]> bufs = null; 1092 int bufCount = 0; 1093 for (;;) { 1094 bufCount = MethodHandleNatives.getMembers(defc, 1095 matchName, matchSig, matchFlags, 1096 lookupClass, 1097 totalCount, buf); 1098 if (bufCount <= buf.length) { 1099 if (bufCount < 0) bufCount = 0; 1100 totalCount += bufCount; 1101 break; 1102 } 1103 // JVM returned to us with an intentional overflow! 1104 totalCount += buf.length; 1105 int excess = bufCount - buf.length; 1106 if (bufs == null) bufs = new ArrayList<>(1); 1107 bufs.add(buf); 1108 int len2 = buf.length; 1109 len2 = Math.max(len2, excess); 1110 len2 = Math.max(len2, totalCount / 4); 1111 buf = newMemberBuffer(Math.min(BUF_MAX, len2)); 1112 } 1113 ArrayList<MemberName> result = new ArrayList<>(totalCount); 1114 if (bufs != null) { 1115 for (MemberName[] buf0 : bufs) { 1116 Collections.addAll(result, buf0); 1117 } 1118 } 1119 result.addAll(Arrays.asList(buf).subList(0, bufCount)); 1120 // Signature matching is not the same as type matching, since 1121 // one signature might correspond to several types. 1122 // So if matchType is a Class or MethodType, refilter the results. 1123 if (matchType != null && matchType != matchSig) { 1124 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) { 1125 MemberName m = it.next(); 1126 if (!matchType.equals(m.getType())) 1127 it.remove(); 1128 } 1129 } 1130 return result; 1131 } 1132 /** Produce a resolved version of the given member. 1133 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1134 * Access checking is performed on behalf of the given {@code lookupClass}. 1135 * If lookup fails or access is not permitted, null is returned. 1136 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. 1137 */ 1138 private static MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { 1139 MemberName m = ref.clone(); // JVM will side-effect the ref 1140 assert(refKind == m.getReferenceKind()); 1141 try { 1142 m = MethodHandleNatives.resolve(m, lookupClass); 1143 m.checkForTypeAlias(); 1144 m.resolution = null; 1145 } catch (LinkageError ex) { 1146 // JVM reports that the "bytecode behavior" would get an error 1147 assert(!m.isResolved()); 1148 m.resolution = ex; 1149 return m; 1150 } 1151 assert(m.referenceKindIsConsistent()); 1152 m.initResolved(true); 1153 assert(m.vminfoIsConsistent()); 1154 // m = m.intern(); // do not intern -- caller should intern instead. 1155 return m; 1156 } 1157 /** Produce a resolved version of the given member. 1158 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1159 * Access checking is performed on behalf of the given {@code lookupClass}. 1160 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown. 1161 * Otherwise the given member or its interned copy is returned, with modifier bits filled in. 1162 */ 1163 public 1164 <NoSuchMemberException extends ReflectiveOperationException> 1165 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, 1166 Class<NoSuchMemberException> nsmClass) 1167 throws IllegalAccessException, NoSuchMemberException { 1168 MemberName result = resolveOrNot(refKind, m, lookupClass); 1169 1170 if (result.isResolved()) { 1171 return result; 1172 } else { // not resolved, throw exception 1173 ReflectiveOperationException ex = result.makeAccessException(); 1174 if (ex instanceof IllegalAccessException) { 1175 throw (IllegalAccessException) ex; 1176 } 1177 throw nsmClass.cast(ex); 1178 } 1179 } 1180 /** Produce a resolved version of the given member. 1181 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1182 * Access checking is performed on behalf of the given {@code lookupClass}. 1183 * If lookup fails or access is not permitted, return null. 1184 * Otherwise the given member or its interned copy is returned, with modifier bits filled in. 1185 */ 1186 public 1187 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { 1188 MemberName result = resolveOrNot(refKind, m, lookupClass); 1189 return result.isResolved() ? result : null; 1190 } 1191 1192 private static 1193 MemberName resolveOrNot(byte refKind, MemberName m, Class<?> lookupClass) { 1194 MemberName result = null; 1195 Class tx_class = m.clazz; // Guess a class for race detection. 1196 while (result == null) { // iterate till no race. 1197 int txn_token = internTxnToken(tx_class); 1198 1199 MemberName result0 = resolve(refKind, m, lookupClass); 1200 1201 if (result0.isResolved()) { 1202 if (result0.clazz != tx_class) { // Confirm/correct guess 1203 Class prev_tx_class = tx_class; 1204 int prev_txn_token = txn_token; 1205 tx_class = result0.clazz; 1206 txn_token = internTxnToken(tx_class); 1207 // The guess may be good enough 1208 if (txn_token != 0 || 1209 prev_txn_token != internTxnToken(prev_tx_class)) { 1210 // Resolved class is different and at least one 1211 // redef occurred, therefore repeat with 1212 // proper class for race consistency checking. 1213 continue; 1214 } 1215 } 1216 result = result0.intern(txn_token); 1217 } else { // Resolution failed, do not intern, return unresolved MemberName 1218 return result0; 1219 } 1220 } 1221 return result; 1222 } 1223 1224 /** Return a list of all methods defined by the given class. 1225 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1226 * Access checking is performed on behalf of the given {@code lookupClass}. 1227 * Inaccessible members are not added to the last. 1228 */ 1229 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 1230 Class<?> lookupClass) { 1231 return getMethods(defc, searchSupers, null, null, lookupClass); 1232 } 1233 /** Return a list of matching methods defined by the given class. 1234 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1235 * Returned methods will match the name (if not null) and the type (if not null). 1236 * Access checking is performed on behalf of the given {@code lookupClass}. 1237 * Inaccessible members are not added to the last. 1238 */ 1239 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers, 1240 String name, MethodType type, Class<?> lookupClass) { 1241 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1242 return getMembers(defc, name, type, matchFlags, lookupClass); 1243 } 1244 /** Return a list of all constructors defined by the given class. 1245 * Access checking is performed on behalf of the given {@code lookupClass}. 1246 * Inaccessible members are not added to the last. 1247 */ 1248 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) { 1249 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); 1250 } 1251 /** Return a list of all fields defined by the given class. 1252 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1253 * Access checking is performed on behalf of the given {@code lookupClass}. 1254 * Inaccessible members are not added to the last. 1255 */ 1256 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 1257 Class<?> lookupClass) { 1258 return getFields(defc, searchSupers, null, null, lookupClass); 1259 } 1260 /** Return a list of all fields defined by the given class. 1261 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1262 * Returned fields will match the name (if not null) and the type (if not null). 1263 * Access checking is performed on behalf of the given {@code lookupClass}. 1264 * Inaccessible members are not added to the last. 1265 */ 1266 public List<MemberName> getFields(Class<?> defc, boolean searchSupers, 1267 String name, Class<?> type, Class<?> lookupClass) { 1268 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1269 return getMembers(defc, name, type, matchFlags, lookupClass); 1270 } 1271 /** Return a list of all nested types defined by the given class. 1272 * Super types are searched (for inherited members) if {@code searchSupers} is true. 1273 * Access checking is performed on behalf of the given {@code lookupClass}. 1274 * Inaccessible members are not added to the last. 1275 */ 1276 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers, 1277 Class<?> lookupClass) { 1278 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); 1279 return getMembers(defc, null, null, matchFlags, lookupClass); 1280 } 1281 private static MemberName[] newMemberBuffer(int length) { 1282 MemberName[] buf = new MemberName[length]; 1283 // fill the buffer with dummy structs for the JVM to fill in 1284 for (int i = 0; i < length; i++) 1285 buf[i] = new MemberName(); 1286 return buf; 1287 } 1288 } 1289 1290 1291 /** 1292 * Lazily create {@link ClassData}. 1293 */ 1294 private static ClassData classData(Class<?> klazz) { 1295 ClassData classData = (ClassData) jla.getClassData(klazz); 1296 if (classData == null) { 1297 classData = new ClassData(); 1298 if (!jla.casClassData(klazz, null, classData)) { 1299 classData = (ClassData) jla.getClassData(klazz); 1300 } 1301 } 1302 return classData; 1303 } 1304 1305 /* package */ static MemberName internMemberName(Class<?> klazz, MemberName memberName, int redefinedCount) { 1306 return classData(klazz).intern(klazz, memberName, redefinedCount); 1307 } 1308 1309 /** 1310 * ClassData 1311 */ 1312 private static class ClassData { 1313 /** 1314 * This needs to be a simple data structure because we need to access 1315 * and update its elements from the JVM. This is a 'tail' pointer 1316 * to last element published to JVM. The chain of elements is 1317 * traversed using {@link MemberName#next} links until {@code null} 1318 * is reached. 1319 */ 1320 private volatile MemberName publishedToVM; 1321 1322 /** 1323 * A linear-scan hash table used for interning. 1324 * The length of the array is always a power of 2, 1325 * greater than (1.5 * size) and less or equal to (3 * size) 1326 */ 1327 private volatile MemberName[] table; 1328 private int size; 1329 1330 /** 1331 * The minimum capacity. 1332 * The value 2 corresponds to an expected maximum size of 1, 1333 * given a load factor of 2/3. MUST be a power of two. 1334 */ 1335 private static final int MINIMUM_CAPACITY = 2; 1336 1337 /** 1338 * The maximum capacity. 1339 * <p/> 1340 * In fact, the table can hold no more than MAXIMUM_CAPACITY-1 elements 1341 * because it has to have at least one slot == null 1342 * in order to avoid infinite loops in get() and putIfAbsent(). 1343 */ 1344 private static final int MAXIMUM_CAPACITY = 1 << 30; 1345 1346 /** 1347 * Interns a member name in the member name table. 1348 * Returns null if a race with the jvm occurred. Races are detected 1349 * by checking for changes in the class redefinition count that occur 1350 * before an intern is complete. 1351 * 1352 * @param klass class whose redefinition count is checked. 1353 * @param memberName member name to be interned 1354 * @param redefinedCount the value of classRedefinedCount() observed before 1355 * creation of the MemberName that is being interned. 1356 * @return null if a race occurred, otherwise the interned MemberName. 1357 */ 1358 @SuppressWarnings({"unchecked", "rawtypes"}) 1359 public MemberName intern(Class<?> klass, MemberName memberName, int redefinedCount) { 1360 1361 // check without holding lock 1362 MemberName internedMemberName = get(memberName); 1363 if (internedMemberName != null) { 1364 return internedMemberName; 1365 } 1366 1367 // must hold lock now 1368 synchronized (this) { 1369 // This has to be a never published MemberName. 1370 assert memberName.next == null; 1371 1372 // First attempt publication to JVM, if that succeeds, 1373 // then try to record in hash table. 1374 memberName.next = publishedToVM; 1375 publishedToVM = memberName; 1376 if (redefinedCount != jla.getClassRedefinedCount(klass)) { 1377 // Lost a race with JVM, back out publication and report failure. 1378 publishedToVM = memberName.next; 1379 // We can't set memberName.next to null here (without a write fence), 1380 // because the write could bubble above the write to publishedToVM! 1381 return null; 1382 } 1383 1384 // Try to record in hash table. 1385 internedMemberName = putIfAbsent(memberName); 1386 if (internedMemberName != null) { 1387 // Lost race with interning, back out JVM publication 1388 // and return already interned element. 1389 publishedToVM = memberName.next; 1390 // We can't set memberName.next to null here (without a write fence), 1391 // because the write could bubble above the write to publishedToVM! 1392 return internedMemberName; 1393 } 1394 1395 // Successfully recorded memberName, return it. 1396 return memberName; 1397 } 1398 } 1399 1400 /** 1401 * Lookup for an interned element. This method can be called without 1402 * any external synchronization. 1403 * 1404 * @param lookupElement the lookup object. 1405 * @return interned element if there is one or null if there is none. 1406 */ 1407 private MemberName get(MemberName lookupElement) { 1408 final MemberName[] tab = table; // volatile read 1409 if (tab == null) { 1410 return null; 1411 } 1412 int i = hash(lookupElement, tab.length); 1413 while (true) { 1414 MemberName element = getVolatile(tab, i); 1415 if (element == null) { 1416 return null; 1417 } 1418 if (element.equals(lookupElement)) { 1419 return element; 1420 } 1421 i = nextKeyIndex(i, tab.length); 1422 } 1423 } 1424 1425 /** 1426 * Inserts new element if there is no interned element equal to it 1427 * already present. This method must be called under exclusive lock. 1428 * 1429 * @param newElement new element to insert. 1430 * @return null if new element was inserted or old element if 1431 * there was one (and no new element was inserted) 1432 */ 1433 private MemberName putIfAbsent(MemberName newElement) { 1434 if (newElement == null) throw new NullPointerException(); 1435 1436 MemberName[] tab = table; // volatile read 1437 1438 if (tab == null) { 1439 // lazily create initial table 1440 tab = new MemberName[MINIMUM_CAPACITY]; 1441 // still virgin 1442 tab[hash(newElement, tab.length)] = newElement; 1443 // publish initial table 1444 table = tab; 1445 size = 1; 1446 return null; 1447 } 1448 1449 while (true) { 1450 1451 int i = hash(newElement, tab.length); 1452 1453 for (MemberName element; 1454 (element = tab[i]) != null; 1455 i = nextKeyIndex(i, tab.length)) { 1456 if (element.equals(newElement)) { 1457 // return existing element 1458 return element; 1459 } 1460 } 1461 1462 final int newSize = size + 1; 1463 1464 MemberName[] newTab; 1465 if ((newTab = resize(tab, newSize)) != null) { // we needed to resize 1466 // publish new table 1467 table = tab = newTab; 1468 // retry loop with new table 1469 } else { // current tab.length is enough 1470 // publish new element 1471 setVolatile(tab, i, newElement); 1472 size = newSize; 1473 return null; 1474 } 1475 } 1476 } 1477 1478 // utility methods 1479 1480 /** 1481 * Re-sizes the table if necessary to hold given number of elements. 1482 * 1483 * @return new table with elements copied to it if resizing was performed 1484 * or null if no resizing is necessary because the table 1485 * has enough room. 1486 */ 1487 private static MemberName[] resize(MemberName[] oldTable, int newSize) { 1488 int oldLength = oldTable.length; 1489 int newLength = oldLength; 1490 // length should always be >= 3 * size / 2. 1491 while (newLength < newSize + (newSize >> 1) && 1492 newLength < MAXIMUM_CAPACITY) { 1493 // next power of 2 1494 newLength <<= 1; 1495 } 1496 if (oldLength == newLength) { // no resizing needed 1497 if (newSize == MAXIMUM_CAPACITY) 1498 throw new IllegalStateException("Capacity exhausted."); 1499 // current length is enough 1500 return null; 1501 } 1502 1503 MemberName[] newTable = new MemberName[newLength]; 1504 1505 // copy elements to new table 1506 for (MemberName element : oldTable) { 1507 if (element != null) { 1508 int i = hash(element, newLength); 1509 while (newTable[i] != null) 1510 i = nextKeyIndex(i, newLength); 1511 newTable[i] = element; 1512 } 1513 } 1514 1515 return newTable; 1516 } 1517 1518 /** 1519 * Returns index for Object x. 1520 */ 1521 private static int hash(Object x, int length) { 1522 int h = x.hashCode(); 1523 return (h ^ (h >>> 16)) & (length - 1); 1524 } 1525 1526 /** 1527 * Circularly traverses table of size length (which is a power of 2). 1528 */ 1529 private static int nextKeyIndex(int i, int length) { 1530 return (i + 1) & (length - 1); 1531 } 1532 1533 // Unsafe machinery 1534 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 1535 private static final long MN_ARRAY_BASE; 1536 private static final int MN_ARRAY_INDEX_SHIFT; 1537 1538 static { 1539 try { 1540 MN_ARRAY_BASE = UNSAFE.arrayBaseOffset( 1541 MemberName[].class 1542 ); 1543 int scale = UNSAFE.arrayIndexScale(MemberName[].class); 1544 if ((scale & (scale - 1)) != 0) 1545 throw new Error("MemberName[] index scale not a power of two"); 1546 MN_ARRAY_INDEX_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); 1547 } catch (Exception e) { 1548 throw new Error(e); 1549 } 1550 } 1551 1552 private static MemberName getVolatile(MemberName[] tab, int i) { 1553 return (MemberName) UNSAFE.getObjectVolatile(tab, arrayOffset(tab, i)); 1554 } 1555 1556 private static void setVolatile(MemberName[] tab, int i, MemberName element) { 1557 UNSAFE.putObjectVolatile(tab, arrayOffset(tab, i), element); 1558 } 1559 1560 private static long arrayOffset(MemberName[] tab, int i) { 1561 if (i < 0 || i >= tab.length) 1562 throw new ArrayIndexOutOfBoundsException(i); 1563 return ((long) i << MN_ARRAY_INDEX_SHIFT) + MN_ARRAY_BASE; 1564 } 1565 } 1566 }