1 /* 2 * Copyright (c) 2008, 2012, 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 java.lang.reflect.*; 29 import sun.invoke.util.ValueConversions; 30 import sun.invoke.util.VerifyAccess; 31 import sun.invoke.util.Wrapper; 32 import java.util.List; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import sun.reflect.Reflection; 36 import static java.lang.invoke.MethodHandleStatics.*; 37 import static java.lang.invoke.MethodHandleNatives.Constants.*; 38 39 /** 40 * This class consists exclusively of static methods that operate on or return 41 * method handles. They fall into several categories: 42 * <ul> 43 * <li>Lookup methods which help create method handles for methods and fields. 44 * <li>Combinator methods, which combine or transform pre-existing method handles into new ones. 45 * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns. 46 * <li>Wrapper methods which can convert between method handles and interface types. 47 * </ul> 48 * <p> 49 * @author John Rose, JSR 292 EG 50 */ 51 public class MethodHandles { 52 53 private MethodHandles() { } // do not instantiate 54 55 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); 56 static { MethodHandleImpl.initStatics(); } 57 // See IMPL_LOOKUP below. 58 59 //// Method handle creation from ordinary methods. 60 61 /** 62 * Returns a {@link Lookup lookup object} on the caller, 63 * which has the capability to access any method handle that the caller has access to, 64 * including direct method handles to private fields and methods. 65 * This lookup object is a <em>capability</em> which may be delegated to trusted agents. 66 * Do not store it in place where untrusted code can access it. 67 */ 68 public static Lookup lookup() { 69 return new Lookup(); 70 } 71 72 /** 73 * Returns a {@link Lookup lookup object} which is trusted minimally. 74 * It can only be used to create method handles to 75 * publicly accessible fields and methods. 76 * <p> 77 * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} 78 * of this lookup object will be {@link java.lang.Object}. 79 * <p> 80 * The lookup class can be changed to any other class {@code C} using an expression of the form 81 * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}. 82 * Since all classes have equal access to public names, 83 * such a change would confer no new access rights. 84 */ 85 public static Lookup publicLookup() { 86 return Lookup.PUBLIC_LOOKUP; 87 } 88 89 /** 90 * A <em>lookup object</em> is a factory for creating method handles, 91 * when the creation requires access checking. 92 * Method handles do not perform 93 * access checks when they are called, but rather when they are created. 94 * Therefore, method handle access 95 * restrictions must be enforced when a method handle is created. 96 * The caller class against which those restrictions are enforced 97 * is known as the {@linkplain #lookupClass lookup class}. 98 * <p> 99 * A lookup class which needs to create method handles will call 100 * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself. 101 * When the {@code Lookup} factory object is created, the identity of the lookup class is 102 * determined, and securely stored in the {@code Lookup} object. 103 * The lookup class (or its delegates) may then use factory methods 104 * on the {@code Lookup} object to create method handles for access-checked members. 105 * This includes all methods, constructors, and fields which are allowed to the lookup class, 106 * even private ones. 107 * <p> 108 * The factory methods on a {@code Lookup} object correspond to all major 109 * use cases for methods, constructors, and fields. 110 * Here is a summary of the correspondence between these factory methods and 111 * the behavior the resulting method handles: 112 * <code> 113 * <table border=1 cellpadding=5 summary="lookup method behaviors"> 114 * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr> 115 * <tr> 116 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> 117 * <td>FT f;</td><td>(T) this.f;</td> 118 * </tr> 119 * <tr> 120 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td> 121 * <td>static<br>FT f;</td><td>(T) C.f;</td> 122 * </tr> 123 * <tr> 124 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td> 125 * <td>FT f;</td><td>this.f = x;</td> 126 * </tr> 127 * <tr> 128 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td> 129 * <td>static<br>FT f;</td><td>C.f = arg;</td> 130 * </tr> 131 * <tr> 132 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td> 133 * <td>T m(A*);</td><td>(T) this.m(arg*);</td> 134 * </tr> 135 * <tr> 136 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td> 137 * <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td> 138 * </tr> 139 * <tr> 140 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td> 141 * <td>T m(A*);</td><td>(T) super.m(arg*);</td> 142 * </tr> 143 * <tr> 144 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td> 145 * <td>C(A*);</td><td>(T) new C(arg*);</td> 146 * </tr> 147 * <tr> 148 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td> 149 * <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td> 150 * </tr> 151 * <tr> 152 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td> 153 * <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td> 154 * </tr> 155 * <tr> 156 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> 157 * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> 158 * </tr> 159 * <tr> 160 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td> 161 * <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td> 162 * </tr> 163 * <tr> 164 * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> 165 * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> 166 * </tr> 167 * </table> 168 * </code> 169 * Here, the type {@code C} is the class or interface being searched for a member, 170 * documented as a parameter named {@code refc} in the lookup methods. 171 * The method or constructor type {@code MT} is composed from the return type {@code T} 172 * and the sequence of argument types {@code A*}. 173 * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. 174 * The formal parameter {@code this} stands for the self-reference of type {@code C}; 175 * if it is present, it is always the leading argument to the method handle invocation. 176 * (In the case of some {@code protected} members, {@code this} may be 177 * restricted in type to the lookup class; see below.) 178 * The name {@code arg} stands for all the other method handle arguments. 179 * In the code examples for the Core Reflection API, the name {@code thisOrNull} 180 * stands for a null reference if the accessed method or field is static, 181 * and {@code this} otherwise. 182 * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand 183 * for reflective objects corresponding to the given members. 184 * <p> 185 * In cases where the given member is of variable arity (i.e., a method or constructor) 186 * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}. 187 * In all other cases, the returned method handle will be of fixed arity. 188 * <p> 189 * The equivalence between looked-up method handles and underlying 190 * class members can break down in a few ways: 191 * <ul> 192 * <li>If {@code C} is not symbolically accessible from the lookup class's loader, 193 * the lookup can still succeed, even when there is no equivalent 194 * Java expression or bytecoded constant. 195 * <li>Likewise, if {@code T} or {@code MT} 196 * is not symbolically accessible from the lookup class's loader, 197 * the lookup can still succeed. 198 * For example, lookups for {@code MethodHandle.invokeExact} and 199 * {@code MethodHandle.invoke} will always succeed, regardless of requested type. 200 * <li>If there is a security manager installed, it can forbid the lookup 201 * on various grounds (<a href="#secmgr">see below</a>). 202 * By contrast, the {@code ldc} instruction is not subject to 203 * security manager checks. 204 * </ul> 205 * 206 * <h3><a name="access"></a>Access checking</h3> 207 * Access checks are applied in the factory methods of {@code Lookup}, 208 * when a method handle is created. 209 * This is a key difference from the Core Reflection API, since 210 * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} 211 * performs access checking against every caller, on every call. 212 * <p> 213 * All access checks start from a {@code Lookup} object, which 214 * compares its recorded lookup class against all requests to 215 * create method handles. 216 * A single {@code Lookup} object can be used to create any number 217 * of access-checked method handles, all checked against a single 218 * lookup class. 219 * <p> 220 * A {@code Lookup} object can be shared with other trusted code, 221 * such as a metaobject protocol. 222 * A shared {@code Lookup} object delegates the capability 223 * to create method handles on private members of the lookup class. 224 * Even if privileged code uses the {@code Lookup} object, 225 * the access checking is confined to the privileges of the 226 * original lookup class. 227 * <p> 228 * A lookup can fail, because 229 * the containing class is not accessible to the lookup class, or 230 * because the desired class member is missing, or because the 231 * desired class member is not accessible to the lookup class. 232 * In any of these cases, a {@code ReflectiveOperationException} will be 233 * thrown from the attempted lookup. The exact class will be one of 234 * the following: 235 * <ul> 236 * <li>NoSuchMethodException — if a method is requested but does not exist 237 * <li>NoSuchFieldException — if a field is requested but does not exist 238 * <li>IllegalAccessException — if the member exists but an access check fails 239 * </ul> 240 * <p> 241 * In general, the conditions under which a method handle may be 242 * looked up for a method {@code M} are exactly equivalent to the conditions 243 * under which the lookup class could have compiled and resolved a call to {@code M}. 244 * And the effect of invoking the method handle resulting from the lookup 245 * is exactly equivalent to executing the compiled and resolved call to {@code M}. 246 * The same point is true of fields and constructors. 247 * <p> 248 * If the desired member is {@code protected}, the usual JVM rules apply, 249 * including the requirement that the lookup class must be either be in the 250 * same package as the desired member, or must inherit that member. 251 * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) 252 * In addition, if the desired member is a non-static field or method 253 * in a different package, the resulting method handle may only be applied 254 * to objects of the lookup class or one of its subclasses. 255 * This requirement is enforced by narrowing the type of the leading 256 * {@code this} parameter from {@code C} 257 * (which will necessarily be a superclass of the lookup class) 258 * to the lookup class itself. 259 * <p> 260 * In some cases, access between nested classes is obtained by the Java compiler by creating 261 * an wrapper method to access a private method of another class 262 * in the same top-level declaration. 263 * For example, a nested class {@code C.D} 264 * can access private members within other related classes such as 265 * {@code C}, {@code C.D.E}, or {@code C.B}, 266 * but the Java compiler may need to generate wrapper methods in 267 * those related classes. In such cases, a {@code Lookup} object on 268 * {@code C.E} would be unable to those private members. 269 * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, 270 * which can transform a lookup on {@code C.E} into one on any of those other 271 * classes, without special elevation of privilege. 272 * <p> 273 * Although bytecode instructions can only refer to classes in 274 * a related class loader, this API can search for methods in any 275 * class, as long as a reference to its {@code Class} object is 276 * available. Such cross-loader references are also possible with the 277 * Core Reflection API, and are impossible to bytecode instructions 278 * such as {@code invokestatic} or {@code getfield}. 279 * There is a {@linkplain java.lang.SecurityManager security manager API} 280 * to allow applications to check such cross-loader references. 281 * These checks apply to both the {@code MethodHandles.Lookup} API 282 * and the Core Reflection API 283 * (as found on {@link java.lang.Class Class}). 284 * <p> 285 * Access checks only apply to named and reflected methods, 286 * constructors, and fields. 287 * Other method handle creation methods, such as 288 * {@link MethodHandle#asType MethodHandle.asType}, 289 * do not require any access checks, and are done 290 * with static methods of {@link MethodHandles}, 291 * independently of any {@code Lookup} object. 292 * 293 * <h3>Security manager interactions</h3> 294 * <a name="secmgr"></a> 295 * If a security manager is present, member lookups are subject to 296 * additional checks. 297 * From one to four calls are made to the security manager. 298 * Any of these calls can refuse access by throwing a 299 * {@link java.lang.SecurityException SecurityException}. 300 * Define {@code smgr} as the security manager, 301 * {@code refc} as the containing class in which the member 302 * is being sought, and {@code defc} as the class in which the 303 * member is actually defined. 304 * The calls are made according to the following rules: 305 * <ul> 306 * <li>In all cases, {@link SecurityManager#checkMemberAccess 307 * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called. 308 * <li>If the class loader of the lookup class is not 309 * the same as or an ancestor of the class loader of {@code refc}, 310 * then {@link SecurityManager#checkPackageAccess 311 * smgr.checkPackageAccess(refcPkg)} is called, 312 * where {@code refcPkg} is the package of {@code refc}. 313 * <li>If the retrieved member is not public, 314 * {@link SecurityManager#checkMemberAccess 315 * smgr.checkMemberAccess(defc, Member.DECLARED)} is called. 316 * (Note that {@code defc} might be the same as {@code refc}.) 317 * The default implementation of this security manager method 318 * inspects the stack to determine the original caller of 319 * the reflective request (such as {@code findStatic}), 320 * and performs additional permission checks if the 321 * class loader of {@code defc} differs from the class 322 * loader of the class from which the reflective request came. 323 * <li>If the retrieved member is not public, 324 * and if {@code defc} and {@code refc} are in different class loaders, 325 * and if the class loader of the lookup class is not 326 * the same as or an ancestor of the class loader of {@code defc}, 327 * then {@link SecurityManager#checkPackageAccess 328 * smgr.checkPackageAccess(defcPkg)} is called, 329 * where {@code defcPkg} is the package of {@code defc}. 330 * </ul> 331 */ 332 // FIXME in MR1: clarify that the bytecode behavior of a caller-ID method (like Class.forName) is relative to the lookupClass used to create the method handle, not the dynamic caller of the method handle 333 public static final 334 class Lookup { 335 /** The class on behalf of whom the lookup is being performed. */ 336 private final Class<?> lookupClass; 337 338 /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */ 339 private final int allowedModes; 340 341 /** A single-bit mask representing {@code public} access, 342 * which may contribute to the result of {@link #lookupModes lookupModes}. 343 * The value, {@code 0x01}, happens to be the same as the value of the 344 * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}. 345 */ 346 public static final int PUBLIC = Modifier.PUBLIC; 347 348 /** A single-bit mask representing {@code private} access, 349 * which may contribute to the result of {@link #lookupModes lookupModes}. 350 * The value, {@code 0x02}, happens to be the same as the value of the 351 * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}. 352 */ 353 public static final int PRIVATE = Modifier.PRIVATE; 354 355 /** A single-bit mask representing {@code protected} access, 356 * which may contribute to the result of {@link #lookupModes lookupModes}. 357 * The value, {@code 0x04}, happens to be the same as the value of the 358 * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}. 359 */ 360 public static final int PROTECTED = Modifier.PROTECTED; 361 362 /** A single-bit mask representing {@code package} access (default access), 363 * which may contribute to the result of {@link #lookupModes lookupModes}. 364 * The value is {@code 0x08}, which does not correspond meaningfully to 365 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. 366 */ 367 public static final int PACKAGE = Modifier.STATIC; 368 369 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE); 370 private static final int TRUSTED = -1; 371 372 private static int fixmods(int mods) { 373 mods &= (ALL_MODES - PACKAGE); 374 return (mods != 0) ? mods : PACKAGE; 375 } 376 377 /** Tells which class is performing the lookup. It is this class against 378 * which checks are performed for visibility and access permissions. 379 * <p> 380 * The class implies a maximum level of access permission, 381 * but the permissions may be additionally limited by the bitmask 382 * {@link #lookupModes lookupModes}, which controls whether non-public members 383 * can be accessed. 384 */ 385 public Class<?> lookupClass() { 386 return lookupClass; 387 } 388 389 // This is just for calling out to MethodHandleImpl. 390 private Class<?> lookupClassOrNull() { 391 return (allowedModes == TRUSTED) ? null : lookupClass; 392 } 393 394 /** Tells which access-protection classes of members this lookup object can produce. 395 * The result is a bit-mask of the bits 396 * {@linkplain #PUBLIC PUBLIC (0x01)}, 397 * {@linkplain #PRIVATE PRIVATE (0x02)}, 398 * {@linkplain #PROTECTED PROTECTED (0x04)}, 399 * and {@linkplain #PACKAGE PACKAGE (0x08)}. 400 * <p> 401 * A freshly-created lookup object 402 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} 403 * has all possible bits set, since the caller class can access all its own members. 404 * A lookup object on a new lookup class 405 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} 406 * may have some mode bits set to zero. 407 * The purpose of this is to restrict access via the new lookup object, 408 * so that it can access only names which can be reached by the original 409 * lookup object, and also by the new lookup class. 410 */ 411 public int lookupModes() { 412 return allowedModes & ALL_MODES; 413 } 414 415 /** Embody the current class (the lookupClass) as a lookup class 416 * for method handle creation. 417 * Must be called by from a method in this package, 418 * which in turn is called by a method not in this package. 419 * <p> 420 * Also, don't make it private, lest javac interpose 421 * an access$N method. 422 */ 423 Lookup() { 424 this(getCallerClassAtEntryPoint(false), ALL_MODES); 425 // make sure we haven't accidentally picked up a privileged class: 426 checkUnprivilegedlookupClass(lookupClass); 427 } 428 429 Lookup(Class<?> lookupClass) { 430 this(lookupClass, ALL_MODES); 431 } 432 433 private Lookup(Class<?> lookupClass, int allowedModes) { 434 this.lookupClass = lookupClass; 435 this.allowedModes = allowedModes; 436 } 437 438 /** 439 * Creates a lookup on the specified new lookup class. 440 * The resulting object will report the specified 441 * class as its own {@link #lookupClass lookupClass}. 442 * <p> 443 * However, the resulting {@code Lookup} object is guaranteed 444 * to have no more access capabilities than the original. 445 * In particular, access capabilities can be lost as follows:<ul> 446 * <li>If the new lookup class differs from the old one, 447 * protected members will not be accessible by virtue of inheritance. 448 * (Protected members may continue to be accessible because of package sharing.) 449 * <li>If the new lookup class is in a different package 450 * than the old one, protected and default (package) members will not be accessible. 451 * <li>If the new lookup class is not within the same package member 452 * as the old one, private members will not be accessible. 453 * <li>If the new lookup class is not accessible to the old lookup class, 454 * then no members, not even public members, will be accessible. 455 * (In all other cases, public members will continue to be accessible.) 456 * </ul> 457 * 458 * @param requestedLookupClass the desired lookup class for the new lookup object 459 * @return a lookup object which reports the desired lookup class 460 * @throws NullPointerException if the argument is null 461 */ 462 public Lookup in(Class<?> requestedLookupClass) { 463 requestedLookupClass.getClass(); // null check 464 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all 465 return new Lookup(requestedLookupClass, ALL_MODES); 466 if (requestedLookupClass == this.lookupClass) 467 return this; // keep same capabilities 468 int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); 469 if ((newModes & PACKAGE) != 0 470 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { 471 newModes &= ~(PACKAGE|PRIVATE); 472 } 473 // Allow nestmate lookups to be created without special privilege: 474 if ((newModes & PRIVATE) != 0 475 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { 476 newModes &= ~PRIVATE; 477 } 478 if ((newModes & PUBLIC) != 0 479 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { 480 // The requested class it not accessible from the lookup class. 481 // No permissions. 482 newModes = 0; 483 } 484 checkUnprivilegedlookupClass(requestedLookupClass); 485 return new Lookup(requestedLookupClass, newModes); 486 } 487 488 // Make sure outer class is initialized first. 489 static { IMPL_NAMES.getClass(); } 490 491 /** Version of lookup which is trusted minimally. 492 * It can only be used to create method handles to 493 * publicly accessible members. 494 */ 495 static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC); 496 497 /** Package-private version of lookup which is trusted. */ 498 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); 499 500 private static void checkUnprivilegedlookupClass(Class<?> lookupClass) { 501 String name = lookupClass.getName(); 502 if (name.startsWith("java.lang.invoke.")) 503 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); 504 } 505 506 /** 507 * Displays the name of the class from which lookups are to be made. 508 * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.) 509 * If there are restrictions on the access permitted to this lookup, 510 * this is indicated by adding a suffix to the class name, consisting 511 * of a slash and a keyword. The keyword represents the strongest 512 * allowed access, and is chosen as follows: 513 * <ul> 514 * <li>If no access is allowed, the suffix is "/noaccess". 515 * <li>If only public access is allowed, the suffix is "/public". 516 * <li>If only public and package access are allowed, the suffix is "/package". 517 * <li>If only public, package, and private access are allowed, the suffix is "/private". 518 * </ul> 519 * If none of the above cases apply, it is the case that full 520 * access (public, package, private, and protected) is allowed. 521 * In this case, no suffix is added. 522 * This is true only of an object obtained originally from 523 * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. 524 * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in} 525 * always have restricted access, and will display a suffix. 526 * <p> 527 * (It may seem strange that protected access should be 528 * stronger than private access. Viewed independently from 529 * package access, protected access is the first to be lost, 530 * because it requires a direct subclass relationship between 531 * caller and callee.) 532 * @see #in 533 */ 534 @Override 535 public String toString() { 536 String cname = lookupClass.getName(); 537 switch (allowedModes) { 538 case 0: // no privileges 539 return cname + "/noaccess"; 540 case PUBLIC: 541 return cname + "/public"; 542 case PUBLIC|PACKAGE: 543 return cname + "/package"; 544 case ALL_MODES & ~PROTECTED: 545 return cname + "/private"; 546 case ALL_MODES: 547 return cname; 548 case TRUSTED: 549 return "/trusted"; // internal only; not exported 550 default: // Should not happen, but it's a bitfield... 551 cname = cname + "/" + Integer.toHexString(allowedModes); 552 assert(false) : cname; 553 return cname; 554 } 555 } 556 557 /* Obtain the external caller class, when called from Lookup.<init> or a first-level subroutine. */ 558 private static Class<?> getCallerClassAtEntryPoint(boolean inSubroutine) { 559 final int CALLER_DEPTH = 4; 560 // Stack for the constructor entry point (inSubroutine=false): 561 // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, 562 // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller 563 // The stack is slightly different for a subroutine of a Lookup.find* method: 564 // 2: Lookup.*, 3: Lookup.find*.*, 4: caller 565 // Note: This should be the only use of getCallerClass in this file. 566 assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class); 567 assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class)); 568 return Reflection.getCallerClass(CALLER_DEPTH); 569 } 570 571 /** 572 * Produces a method handle for a static method. 573 * The type of the method handle will be that of the method. 574 * (Since static methods do not take receivers, there is no 575 * additional receiver argument inserted into the method handle type, 576 * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.) 577 * The method and all its argument types must be accessible to the lookup class. 578 * If the method's class has not yet been initialized, that is done 579 * immediately, before the method handle is returned. 580 * <p> 581 * The returned method handle will have 582 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 583 * the method's variable arity modifier bit ({@code 0x0080}) is set. 584 * @param refc the class from which the method is accessed 585 * @param name the name of the method 586 * @param type the type of the method 587 * @return the desired method handle 588 * @throws NoSuchMethodException if the method does not exist 589 * @throws IllegalAccessException if access checking fails, 590 * or if the method is not {@code static}, 591 * or if the method's variable arity modifier bit 592 * is set and {@code asVarargsCollector} fails 593 * @exception SecurityException if a security manager is present and it 594 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 595 * @throws NullPointerException if any argument is null 596 */ 597 public 598 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 599 MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); 600 checkSecurityManager(refc, method); // stack walk magic: do not refactor 601 return getDirectMethod(REF_invokeStatic, refc, method); 602 } 603 604 /** 605 * Produces a method handle for a virtual method. 606 * The type of the method handle will be that of the method, 607 * with the receiver type (usually {@code refc}) prepended. 608 * The method and all its argument types must be accessible to the lookup class. 609 * <p> 610 * When called, the handle will treat the first argument as a receiver 611 * and dispatch on the receiver's type to determine which method 612 * implementation to enter. 613 * (The dispatching action is identical with that performed by an 614 * {@code invokevirtual} or {@code invokeinterface} instruction.) 615 * <p> 616 * The first argument will be of type {@code refc} if the lookup 617 * class has full privileges to access the member. Otherwise 618 * the member must be {@code protected} and the first argument 619 * will be restricted in type to the lookup class. 620 * <p> 621 * The returned method handle will have 622 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 623 * the method's variable arity modifier bit ({@code 0x0080}) is set. 624 * <p> 625 * Because of the general equivalence between {@code invokevirtual} 626 * instructions and method handles produced by {@code findVirtual}, 627 * if the class is {@code MethodHandle} and the name string is 628 * {@code invokeExact} or {@code invoke}, the resulting 629 * method handle is equivalent to one produced by 630 * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or 631 * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker} 632 * with the same {@code type} argument. 633 * 634 * @param refc the class or interface from which the method is accessed 635 * @param name the name of the method 636 * @param type the type of the method, with the receiver argument omitted 637 * @return the desired method handle 638 * @throws NoSuchMethodException if the method does not exist 639 * @throws IllegalAccessException if access checking fails, 640 * or if the method is {@code static} 641 * or if the method's variable arity modifier bit 642 * is set and {@code asVarargsCollector} fails 643 * @exception SecurityException if a security manager is present and it 644 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 645 * @throws NullPointerException if any argument is null 646 */ 647 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 648 if (refc == MethodHandle.class) { 649 MethodHandle mh = findVirtualForMH(name, type); 650 if (mh != null) return mh; 651 } 652 byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); 653 MemberName method = resolveOrFail(refKind, refc, name, type); 654 checkSecurityManager(refc, method); // stack walk magic: do not refactor 655 return getDirectMethod(refKind, refc, method); 656 } 657 private MethodHandle findVirtualForMH(String name, MethodType type) { 658 // these names require special lookups because of the implicit MethodType argument 659 if ("invoke".equals(name)) 660 return invoker(type); 661 if ("invokeExact".equals(name)) 662 return exactInvoker(type); 663 return null; 664 } 665 666 /** 667 * Produces a method handle which creates an object and initializes it, using 668 * the constructor of the specified type. 669 * The parameter types of the method handle will be those of the constructor, 670 * while the return type will be a reference to the constructor's class. 671 * The constructor and all its argument types must be accessible to the lookup class. 672 * If the constructor's class has not yet been initialized, that is done 673 * immediately, before the method handle is returned. 674 * <p> 675 * Note: The requested type must have a return type of {@code void}. 676 * This is consistent with the JVM's treatment of constructor type descriptors. 677 * <p> 678 * The returned method handle will have 679 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 680 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 681 * @param refc the class or interface from which the method is accessed 682 * @param type the type of the method, with the receiver argument omitted, and a void return type 683 * @return the desired method handle 684 * @throws NoSuchMethodException if the constructor does not exist 685 * @throws IllegalAccessException if access checking fails 686 * or if the method's variable arity modifier bit 687 * is set and {@code asVarargsCollector} fails 688 * @exception SecurityException if a security manager is present and it 689 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 690 * @throws NullPointerException if any argument is null 691 */ 692 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { 693 String name = "<init>"; 694 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); 695 checkSecurityManager(refc, ctor); // stack walk magic: do not refactor 696 return getDirectConstructor(refc, ctor); 697 } 698 699 /** 700 * Produces an early-bound method handle for a virtual method, 701 * as if called from an {@code invokespecial} 702 * instruction from {@code caller}. 703 * The type of the method handle will be that of the method, 704 * with a suitably restricted receiver type (such as {@code caller}) prepended. 705 * The method and all its argument types must be accessible 706 * to the caller. 707 * <p> 708 * When called, the handle will treat the first argument as a receiver, 709 * but will not dispatch on the receiver's type. 710 * (This direct invocation action is identical with that performed by an 711 * {@code invokespecial} instruction.) 712 * <p> 713 * If the explicitly specified caller class is not identical with the 714 * lookup class, or if this lookup object does not have private access 715 * privileges, the access fails. 716 * <p> 717 * The returned method handle will have 718 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 719 * the method's variable arity modifier bit ({@code 0x0080}) is set. 720 * @param refc the class or interface from which the method is accessed 721 * @param name the name of the method (which must not be "<init>") 722 * @param type the type of the method, with the receiver argument omitted 723 * @param specialCaller the proposed calling class to perform the {@code invokespecial} 724 * @return the desired method handle 725 * @throws NoSuchMethodException if the method does not exist 726 * @throws IllegalAccessException if access checking fails 727 * or if the method's variable arity modifier bit 728 * is set and {@code asVarargsCollector} fails 729 * @exception SecurityException if a security manager is present and it 730 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 731 * @throws NullPointerException if any argument is null 732 */ 733 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, 734 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { 735 checkSpecialCaller(specialCaller); 736 Lookup specialLookup = this.in(specialCaller); 737 MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); 738 checkSecurityManager(refc, method); // stack walk magic: do not refactor 739 return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method); 740 } 741 742 /** 743 * Produces a method handle giving read access to a non-static field. 744 * The type of the method handle will have a return type of the field's 745 * value type. 746 * The method handle's single argument will be the instance containing 747 * the field. 748 * Access checking is performed immediately on behalf of the lookup class. 749 * @param refc the class or interface from which the method is accessed 750 * @param name the field's name 751 * @param type the field's type 752 * @return a method handle which can load values from the field 753 * @throws NoSuchFieldException if the field does not exist 754 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} 755 * @exception SecurityException if a security manager is present and it 756 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 757 * @throws NullPointerException if any argument is null 758 */ 759 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 760 MemberName field = resolveOrFail(REF_getField, refc, name, type); 761 checkSecurityManager(refc, field); // stack walk magic: do not refactor 762 return getDirectField(REF_getField, refc, field); 763 } 764 765 /** 766 * Produces a method handle giving write access to a non-static field. 767 * The type of the method handle will have a void return type. 768 * The method handle will take two arguments, the instance containing 769 * the field, and the value to be stored. 770 * The second argument will be of the field's value type. 771 * Access checking is performed immediately on behalf of the lookup class. 772 * @param refc the class or interface from which the method is accessed 773 * @param name the field's name 774 * @param type the field's type 775 * @return a method handle which can store values into the field 776 * @throws NoSuchFieldException if the field does not exist 777 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} 778 * @exception SecurityException if a security manager is present and it 779 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 780 * @throws NullPointerException if any argument is null 781 */ 782 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 783 MemberName field = resolveOrFail(REF_putField, refc, name, type); 784 checkSecurityManager(refc, field); // stack walk magic: do not refactor 785 return getDirectField(REF_putField, refc, field); 786 } 787 788 /** 789 * Produces a method handle giving read access to a static field. 790 * The type of the method handle will have a return type of the field's 791 * value type. 792 * The method handle will take no arguments. 793 * Access checking is performed immediately on behalf of the lookup class. 794 * @param refc the class or interface from which the method is accessed 795 * @param name the field's name 796 * @param type the field's type 797 * @return a method handle which can load values from the field 798 * @throws NoSuchFieldException if the field does not exist 799 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} 800 * @exception SecurityException if a security manager is present and it 801 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 802 * @throws NullPointerException if any argument is null 803 */ 804 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 805 MemberName field = resolveOrFail(REF_getStatic, refc, name, type); 806 checkSecurityManager(refc, field); // stack walk magic: do not refactor 807 return getDirectField(REF_getStatic, refc, field); 808 } 809 810 /** 811 * Produces a method handle giving write access to a static field. 812 * The type of the method handle will have a void return type. 813 * The method handle will take a single 814 * argument, of the field's value type, the value to be stored. 815 * Access checking is performed immediately on behalf of the lookup class. 816 * @param refc the class or interface from which the method is accessed 817 * @param name the field's name 818 * @param type the field's type 819 * @return a method handle which can store values into the field 820 * @throws NoSuchFieldException if the field does not exist 821 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} 822 * @exception SecurityException if a security manager is present and it 823 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 824 * @throws NullPointerException if any argument is null 825 */ 826 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 827 MemberName field = resolveOrFail(REF_putStatic, refc, name, type); 828 checkSecurityManager(refc, field); // stack walk magic: do not refactor 829 return getDirectField(REF_putStatic, refc, field); 830 } 831 832 /** 833 * Produces an early-bound method handle for a non-static method. 834 * The receiver must have a supertype {@code defc} in which a method 835 * of the given name and type is accessible to the lookup class. 836 * The method and all its argument types must be accessible to the lookup class. 837 * The type of the method handle will be that of the method, 838 * without any insertion of an additional receiver parameter. 839 * The given receiver will be bound into the method handle, 840 * so that every call to the method handle will invoke the 841 * requested method on the given receiver. 842 * <p> 843 * The returned method handle will have 844 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 845 * the method's variable arity modifier bit ({@code 0x0080}) is set 846 * <em>and</em> the trailing array argument is not the only argument. 847 * (If the trailing array argument is the only argument, 848 * the given receiver value will be bound to it.) 849 * <p> 850 * This is equivalent to the following code: 851 * <blockquote><pre> 852 import static java.lang.invoke.MethodHandles.*; 853 import static java.lang.invoke.MethodType.*; 854 ... 855 MethodHandle mh0 = lookup().{@link #findVirtual findVirtual}(defc, name, type); 856 MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver); 857 MethodType mt1 = mh1.type(); 858 if (mh0.isVarargsCollector()) 859 mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); 860 return mh1; 861 * </pre></blockquote> 862 * where {@code defc} is either {@code receiver.getClass()} or a super 863 * type of that class, in which the requested method is accessible 864 * to the lookup class. 865 * (Note that {@code bindTo} does not preserve variable arity.) 866 * @param receiver the object from which the method is accessed 867 * @param name the name of the method 868 * @param type the type of the method, with the receiver argument omitted 869 * @return the desired method handle 870 * @throws NoSuchMethodException if the method does not exist 871 * @throws IllegalAccessException if access checking fails 872 * or if the method's variable arity modifier bit 873 * is set and {@code asVarargsCollector} fails 874 * @exception SecurityException if a security manager is present and it 875 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 876 * @throws NullPointerException if any argument is null 877 */ 878 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 879 Class<? extends Object> refc = receiver.getClass(); // may get NPE 880 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); 881 checkSecurityManager(refc, method); // stack walk magic: do not refactor 882 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method); 883 return mh.bindReceiver(receiver).setVarargs(method); 884 } 885 886 /** 887 * Makes a direct method handle to <i>m</i>, if the lookup class has permission. 888 * If <i>m</i> is non-static, the receiver argument is treated as an initial argument. 889 * If <i>m</i> is virtual, overriding is respected on every call. 890 * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped. 891 * The type of the method handle will be that of the method, 892 * with the receiver type prepended (but only if it is non-static). 893 * If the method's {@code accessible} flag is not set, 894 * access checking is performed immediately on behalf of the lookup class. 895 * If <i>m</i> is not public, do not share the resulting handle with untrusted parties. 896 * <p> 897 * The returned method handle will have 898 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 899 * the method's variable arity modifier bit ({@code 0x0080}) is set. 900 * @param m the reflected method 901 * @return a method handle which can invoke the reflected method 902 * @throws IllegalAccessException if access checking fails 903 * or if the method's variable arity modifier bit 904 * is set and {@code asVarargsCollector} fails 905 * @throws NullPointerException if the argument is null 906 */ 907 public MethodHandle unreflect(Method m) throws IllegalAccessException { 908 MemberName method = new MemberName(m); 909 byte refKind = method.getReferenceKind(); 910 if (refKind == REF_invokeSpecial) 911 refKind = REF_invokeVirtual; 912 assert(method.isMethod()); 913 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; 914 return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method); 915 } 916 917 /** 918 * Produces a method handle for a reflected method. 919 * It will bypass checks for overriding methods on the receiver, 920 * as if by a {@code invokespecial} instruction from within the {@code specialCaller}. 921 * The type of the method handle will be that of the method, 922 * with the special caller type prepended (and <em>not</em> the receiver of the method). 923 * If the method's {@code accessible} flag is not set, 924 * access checking is performed immediately on behalf of the lookup class, 925 * as if {@code invokespecial} instruction were being linked. 926 * <p> 927 * The returned method handle will have 928 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 929 * the method's variable arity modifier bit ({@code 0x0080}) is set. 930 * @param m the reflected method 931 * @param specialCaller the class nominally calling the method 932 * @return a method handle which can invoke the reflected method 933 * @throws IllegalAccessException if access checking fails 934 * or if the method's variable arity modifier bit 935 * is set and {@code asVarargsCollector} fails 936 * @throws NullPointerException if any argument is null 937 */ 938 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { 939 checkSpecialCaller(specialCaller); 940 Lookup specialLookup = this.in(specialCaller); 941 MemberName method = new MemberName(m, true); 942 assert(method.isMethod()); 943 // ignore m.isAccessible: this is a new kind of access 944 return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method); 945 } 946 947 /** 948 * Produces a method handle for a reflected constructor. 949 * The type of the method handle will be that of the constructor, 950 * with the return type changed to the declaring class. 951 * The method handle will perform a {@code newInstance} operation, 952 * creating a new instance of the constructor's class on the 953 * arguments passed to the method handle. 954 * <p> 955 * If the constructor's {@code accessible} flag is not set, 956 * access checking is performed immediately on behalf of the lookup class. 957 * <p> 958 * The returned method handle will have 959 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 960 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 961 * @param c the reflected constructor 962 * @return a method handle which can invoke the reflected constructor 963 * @throws IllegalAccessException if access checking fails 964 * or if the method's variable arity modifier bit 965 * is set and {@code asVarargsCollector} fails 966 * @throws NullPointerException if the argument is null 967 */ 968 @SuppressWarnings("rawtypes") // Will be Constructor<?> after JSR 292 MR 969 public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { 970 MemberName ctor = new MemberName(c); 971 assert(ctor.isConstructor()); 972 Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; 973 return lookup.getDirectConstructor(ctor.getDeclaringClass(), ctor); 974 } 975 976 /** 977 * Produces a method handle giving read access to a reflected field. 978 * The type of the method handle will have a return type of the field's 979 * value type. 980 * If the field is static, the method handle will take no arguments. 981 * Otherwise, its single argument will be the instance containing 982 * the field. 983 * If the field's {@code accessible} flag is not set, 984 * access checking is performed immediately on behalf of the lookup class. 985 * @param f the reflected field 986 * @return a method handle which can load values from the reflected field 987 * @throws IllegalAccessException if access checking fails 988 * @throws NullPointerException if the argument is null 989 */ 990 public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { 991 return unreflectField(f, false); 992 } 993 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { 994 MemberName field = new MemberName(f, isSetter); 995 assert(isSetter 996 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) 997 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); 998 Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; 999 return lookup.getDirectField(field.getReferenceKind(), f.getDeclaringClass(), field); 1000 } 1001 1002 /** 1003 * Produces a method handle giving write access to a reflected field. 1004 * The type of the method handle will have a void return type. 1005 * If the field is static, the method handle will take a single 1006 * argument, of the field's value type, the value to be stored. 1007 * Otherwise, the two arguments will be the instance containing 1008 * the field, and the value to be stored. 1009 * If the field's {@code accessible} flag is not set, 1010 * access checking is performed immediately on behalf of the lookup class. 1011 * @param f the reflected field 1012 * @return a method handle which can store values into the reflected field 1013 * @throws IllegalAccessException if access checking fails 1014 * @throws NullPointerException if the argument is null 1015 */ 1016 public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { 1017 return unreflectField(f, true); 1018 } 1019 1020 /// Helper methods, all package-private. 1021 1022 MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 1023 checkSymbolicClass(refc); // do this before attempting to resolve 1024 name.getClass(); type.getClass(); // NPE 1025 return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), 1026 NoSuchFieldException.class); 1027 } 1028 1029 MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 1030 checkSymbolicClass(refc); // do this before attempting to resolve 1031 name.getClass(); type.getClass(); // NPE 1032 return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), 1033 NoSuchMethodException.class); 1034 } 1035 1036 void checkSymbolicClass(Class<?> refc) throws IllegalAccessException { 1037 Class<?> caller = lookupClassOrNull(); 1038 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) 1039 throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); 1040 } 1041 1042 /** 1043 * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. 1044 * This function performs stack walk magic: do not refactor it. 1045 */ 1046 void checkSecurityManager(Class<?> refc, MemberName m) { 1047 SecurityManager smgr = System.getSecurityManager(); 1048 if (smgr == null) return; 1049 if (allowedModes == TRUSTED) return; 1050 // Step 1: 1051 smgr.checkMemberAccess(refc, Member.PUBLIC); 1052 // Step 2: 1053 Class<?> callerClass = ((allowedModes & PRIVATE) != 0 1054 ? lookupClass // for strong access modes, no extra check 1055 // next line does stack walk magic; do not refactor: 1056 : getCallerClassAtEntryPoint(true)); 1057 if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || 1058 (callerClass != lookupClass && 1059 !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) 1060 smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); 1061 // Step 3: 1062 if (m.isPublic()) return; 1063 Class<?> defc = m.getDeclaringClass(); 1064 smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE 1065 // Step 4: 1066 if (defc != refc) 1067 smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); 1068 1069 // Comment from SM.checkMemberAccess, where which=DECLARED: 1070 /* 1071 * stack depth of 4 should be the caller of one of the 1072 * methods in java.lang.Class that invoke checkMember 1073 * access. The stack should look like: 1074 * 1075 * someCaller [3] 1076 * java.lang.Class.someReflectionAPI [2] 1077 * java.lang.Class.checkMemberAccess [1] 1078 * SecurityManager.checkMemberAccess [0] 1079 * 1080 */ 1081 // For us it is this stack: 1082 // someCaller [3] 1083 // Lookup.findSomeMember [2] 1084 // Lookup.checkSecurityManager [1] 1085 // SecurityManager.checkMemberAccess [0] 1086 } 1087 1088 void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { 1089 boolean wantStatic = (refKind == REF_invokeStatic); 1090 String message; 1091 if (m.isConstructor()) 1092 message = "expected a method, not a constructor"; 1093 else if (!m.isMethod()) 1094 message = "expected a method"; 1095 else if (wantStatic != m.isStatic()) 1096 message = wantStatic ? "expected a static method" : "expected a non-static method"; 1097 else 1098 { checkAccess(refKind, refc, m); return; } 1099 throw m.makeAccessException(message, this); 1100 } 1101 1102 void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { 1103 boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind); 1104 String message; 1105 if (wantStatic != m.isStatic()) 1106 message = wantStatic ? "expected a static field" : "expected a non-static field"; 1107 else 1108 { checkAccess(refKind, refc, m); return; } 1109 throw m.makeAccessException(message, this); 1110 } 1111 1112 void checkAccess(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { 1113 assert(m.referenceKindIsConsistentWith(refKind) && 1114 MethodHandleNatives.refKindIsValid(refKind) && 1115 (MethodHandleNatives.refKindIsField(refKind) == m.isField())); 1116 int allowedModes = this.allowedModes; 1117 if (allowedModes == TRUSTED) return; 1118 int mods = m.getModifiers(); 1119 if (Modifier.isFinal(mods) && 1120 MethodHandleNatives.refKindIsSetter(refKind)) 1121 throw m.makeAccessException("unexpected set of a final field", this); 1122 if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0) 1123 return; // common case 1124 int requestedModes = fixmods(mods); // adjust 0 => PACKAGE 1125 if ((requestedModes & allowedModes) != 0) { 1126 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(), 1127 mods, lookupClass(), allowedModes)) 1128 return; 1129 } else { 1130 // Protected members can also be checked as if they were package-private. 1131 if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0 1132 && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass())) 1133 return; 1134 } 1135 throw m.makeAccessException(accessFailedMessage(refc, m), this); 1136 } 1137 1138 String accessFailedMessage(Class<?> refc, MemberName m) { 1139 Class<?> defc = m.getDeclaringClass(); 1140 int mods = m.getModifiers(); 1141 // check the class first: 1142 boolean classOK = (Modifier.isPublic(defc.getModifiers()) && 1143 (defc == refc || 1144 Modifier.isPublic(refc.getModifiers()))); 1145 if (!classOK && (allowedModes & PACKAGE) != 0) { 1146 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) && 1147 (defc == refc || 1148 VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); 1149 } 1150 if (!classOK) 1151 return "class is not public"; 1152 if (Modifier.isPublic(mods)) 1153 return "access to public member failed"; // (how?) 1154 if (Modifier.isPrivate(mods)) 1155 return "member is private"; 1156 if (Modifier.isProtected(mods)) 1157 return "member is protected"; 1158 return "member is private to package"; 1159 } 1160 1161 private static final boolean ALLOW_NESTMATE_ACCESS = false; 1162 1163 private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { 1164 int allowedModes = this.allowedModes; 1165 if (allowedModes == TRUSTED) return; 1166 if ((allowedModes & PRIVATE) == 0 1167 || (specialCaller != lookupClass() 1168 && !(ALLOW_NESTMATE_ACCESS && 1169 VerifyAccess.isSamePackageMember(specialCaller, lookupClass())))) 1170 throw new MemberName(specialCaller). 1171 makeAccessException("no private access for invokespecial", this); 1172 } 1173 1174 private boolean restrictProtectedReceiver(MemberName method) { 1175 // The accessing class only has the right to use a protected member 1176 // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. 1177 if (!method.isProtected() || method.isStatic() 1178 || allowedModes == TRUSTED 1179 || method.getDeclaringClass() == lookupClass() 1180 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()) 1181 || (ALLOW_NESTMATE_ACCESS && 1182 VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))) 1183 return false; 1184 return true; 1185 } 1186 private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException { 1187 assert(!method.isStatic()); 1188 // receiver type of mh is too wide; narrow to caller 1189 if (!method.getDeclaringClass().isAssignableFrom(caller)) { 1190 throw method.makeAccessException("caller class must be a subclass below the method", caller); 1191 } 1192 MethodType rawType = mh.type(); 1193 if (rawType.parameterType(0) == caller) return mh; 1194 MethodType narrowType = rawType.changeParameterType(0, caller); 1195 return mh.viewAsType(narrowType); 1196 } 1197 1198 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException { 1199 return getDirectMethodCommon(refKind, refc, method, 1200 (refKind == REF_invokeSpecial || 1201 (MethodHandleNatives.refKindHasReceiver(refKind) && 1202 restrictProtectedReceiver(method)))); 1203 } 1204 private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException { 1205 return getDirectMethodCommon(refKind, refc, method, false); 1206 } 1207 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method, 1208 boolean doRestrict) throws IllegalAccessException { 1209 checkMethod(refKind, refc, method); 1210 if (method.isMethodHandleInvoke()) 1211 return fakeMethodHandleInvoke(method); 1212 MethodHandle mh = DirectMethodHandle.make(refc, method); 1213 mh = maybeBindCaller(method, mh); 1214 mh = mh.setVarargs(method); 1215 if (doRestrict) 1216 mh = restrictReceiver(method, mh, lookupClass()); 1217 return mh; 1218 } 1219 private MethodHandle fakeMethodHandleInvoke(MemberName method) { 1220 return throwException(method.getReturnType(), UnsupportedOperationException.class); 1221 } 1222 private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { 1223 if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) 1224 return mh; 1225 Class<?> hostClass = lookupClass; 1226 if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup 1227 hostClass = null; 1228 MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); 1229 // Note: caller will apply varargs after this step happens. 1230 return cbmh; 1231 } 1232 private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException { 1233 checkField(refKind, refc, field); 1234 MethodHandle mh = DirectMethodHandle.make(refc, field); 1235 boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) && 1236 restrictProtectedReceiver(field)); 1237 if (doRestrict) 1238 mh = restrictReceiver(field, mh, lookupClass()); 1239 return mh; 1240 } 1241 private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException { 1242 assert(ctor.isConstructor()); 1243 checkAccess(REF_newInvokeSpecial, refc, ctor); 1244 assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here 1245 return DirectMethodHandle.make(ctor).setVarargs(ctor); 1246 } 1247 1248 /** Hook called from the JVM (via MethodHandleNatives) to link MH constants: 1249 */ 1250 /*non-public*/ 1251 MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException { 1252 MemberName resolved = null; 1253 if (type instanceof MemberName) { 1254 resolved = (MemberName) type; 1255 if (!resolved.isResolved()) throw new InternalError("unresolved MemberName"); 1256 assert(name == null || name.equals(resolved.getName())); 1257 } 1258 if (MethodHandleNatives.refKindIsField(refKind)) { 1259 MemberName field = (resolved != null) ? resolved 1260 : resolveOrFail(refKind, defc, name, (Class<?>) type); 1261 return getDirectField(refKind, defc, field); 1262 } else if (MethodHandleNatives.refKindIsMethod(refKind)) { 1263 MemberName method = (resolved != null) ? resolved 1264 : resolveOrFail(refKind, defc, name, (MethodType) type); 1265 return getDirectMethod(refKind, defc, method); 1266 } else if (refKind == REF_newInvokeSpecial) { 1267 assert(name == null || name.equals("<init>")); 1268 MemberName ctor = (resolved != null) ? resolved 1269 : resolveOrFail(REF_newInvokeSpecial, defc, name, (MethodType) type); 1270 return getDirectConstructor(defc, ctor); 1271 } 1272 // oops 1273 throw new ReflectiveOperationException("bad MethodHandle constant #"+refKind+" "+name+" : "+type); 1274 } 1275 } 1276 1277 /** 1278 * Produces a method handle giving read access to elements of an array. 1279 * The type of the method handle will have a return type of the array's 1280 * element type. Its first argument will be the array type, 1281 * and the second will be {@code int}. 1282 * @param arrayClass an array type 1283 * @return a method handle which can load values from the given array type 1284 * @throws NullPointerException if the argument is null 1285 * @throws IllegalArgumentException if arrayClass is not an array type 1286 */ 1287 public static 1288 MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException { 1289 return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false); 1290 } 1291 1292 /** 1293 * Produces a method handle giving write access to elements of an array. 1294 * The type of the method handle will have a void return type. 1295 * Its last argument will be the array's element type. 1296 * The first and second arguments will be the array type and int. 1297 * @return a method handle which can store values into the array type 1298 * @throws NullPointerException if the argument is null 1299 * @throws IllegalArgumentException if arrayClass is not an array type 1300 */ 1301 public static 1302 MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException { 1303 return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true); 1304 } 1305 1306 /// method handle invocation (reflective style) 1307 1308 /** 1309 * Produces a method handle which will invoke any method handle of the 1310 * given {@code type}, with a given number of trailing arguments replaced by 1311 * a single trailing {@code Object[]} array. 1312 * The resulting invoker will be a method handle with the following 1313 * arguments: 1314 * <ul> 1315 * <li>a single {@code MethodHandle} target 1316 * <li>zero or more leading values (counted by {@code leadingArgCount}) 1317 * <li>an {@code Object[]} array containing trailing arguments 1318 * </ul> 1319 * <p> 1320 * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with 1321 * the indicated {@code type}. 1322 * That is, if the target is exactly of the given {@code type}, it will behave 1323 * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType} 1324 * is used to convert the target to the required {@code type}. 1325 * <p> 1326 * The type of the returned invoker will not be the given {@code type}, but rather 1327 * will have all parameters except the first {@code leadingArgCount} 1328 * replaced by a single array of type {@code Object[]}, which will be 1329 * the final parameter. 1330 * <p> 1331 * Before invoking its target, the invoker will spread the final array, apply 1332 * reference casts as necessary, and unbox and widen primitive arguments. 1333 * <p> 1334 * This method is equivalent to the following code (though it may be more efficient): 1335 * <p><blockquote><pre> 1336 MethodHandle invoker = MethodHandles.invoker(type); 1337 int spreadArgCount = type.parameterCount() - leadingArgCount; 1338 invoker = invoker.asSpreader(Object[].class, spreadArgCount); 1339 return invoker; 1340 * </pre></blockquote> 1341 * <p> 1342 * This method throws no reflective or security exceptions. 1343 * @param type the desired target type 1344 * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target 1345 * @return a method handle suitable for invoking any method handle of the given type 1346 * @throws NullPointerException if {@code type} is null 1347 * @throws IllegalArgumentException if {@code leadingArgCount} is not in 1348 * the range from 0 to {@code type.parameterCount()} inclusive 1349 */ 1350 static public 1351 MethodHandle spreadInvoker(MethodType type, int leadingArgCount) { 1352 if (leadingArgCount < 0 || leadingArgCount > type.parameterCount()) 1353 throw new IllegalArgumentException("bad argument count "+leadingArgCount); 1354 return type.invokers().spreadInvoker(leadingArgCount); 1355 } 1356 1357 /** 1358 * Produces a special <em>invoker method handle</em> which can be used to 1359 * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}. 1360 * The resulting invoker will have a type which is 1361 * exactly equal to the desired type, except that it will accept 1362 * an additional leading argument of type {@code MethodHandle}. 1363 * <p> 1364 * This method is equivalent to the following code (though it may be more efficient): 1365 * <p><blockquote><pre> 1366 publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) 1367 * </pre></blockquote> 1368 * 1369 * <p style="font-size:smaller;"> 1370 * <em>Discussion:</em> 1371 * Invoker method handles can be useful when working with variable method handles 1372 * of unknown types. 1373 * For example, to emulate an {@code invokeExact} call to a variable method 1374 * handle {@code M}, extract its type {@code T}, 1375 * look up the invoker method {@code X} for {@code T}, 1376 * and call the invoker method, as {@code X.invoke(T, A...)}. 1377 * (It would not work to call {@code X.invokeExact}, since the type {@code T} 1378 * is unknown.) 1379 * If spreading, collecting, or other argument transformations are required, 1380 * they can be applied once to the invoker {@code X} and reused on many {@code M} 1381 * method handle values, as long as they are compatible with the type of {@code X}. 1382 * <p> 1383 * <em>(Note: The invoker method is not available via the Core Reflection API. 1384 * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} 1385 * on the declared {@code invokeExact} or {@code invoke} method will raise an 1386 * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> 1387 * <p> 1388 * This method throws no reflective or security exceptions. 1389 * @param type the desired target type 1390 * @return a method handle suitable for invoking any method handle of the given type 1391 */ 1392 static public 1393 MethodHandle exactInvoker(MethodType type) { 1394 return type.invokers().exactInvoker(); 1395 } 1396 1397 /** 1398 * Produces a special <em>invoker method handle</em> which can be used to 1399 * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}. 1400 * The resulting invoker will have a type which is 1401 * exactly equal to the desired type, except that it will accept 1402 * an additional leading argument of type {@code MethodHandle}. 1403 * <p> 1404 * Before invoking its target, if the target differs from the expected type, 1405 * the invoker will apply reference casts as 1406 * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}. 1407 * Similarly, the return value will be converted as necessary. 1408 * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle}, 1409 * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}. 1410 * <p> 1411 * A {@linkplain MethodType#genericMethodType general method type}, 1412 * mentions only {@code Object} arguments and return values. 1413 * An invoker for such a type is capable of calling any method handle 1414 * of the same arity as the general type. 1415 * <p> 1416 * This method is equivalent to the following code (though it may be more efficient): 1417 * <p><blockquote><pre> 1418 publicLookup().findVirtual(MethodHandle.class, "invoke", type) 1419 * </pre></blockquote> 1420 * <p> 1421 * This method throws no reflective or security exceptions. 1422 * @param type the desired target type 1423 * @return a method handle suitable for invoking any method handle convertible to the given type 1424 */ 1425 static public 1426 MethodHandle invoker(MethodType type) { 1427 return type.invokers().generalInvoker(); 1428 } 1429 1430 static /*non-public*/ 1431 MethodHandle basicInvoker(MethodType type) { 1432 return type.form().basicInvoker(); 1433 } 1434 1435 /// method handle modification (creation from other method handles) 1436 1437 /** 1438 * Produces a method handle which adapts the type of the 1439 * given method handle to a new type by pairwise argument and return type conversion. 1440 * The original type and new type must have the same number of arguments. 1441 * The resulting method handle is guaranteed to report a type 1442 * which is equal to the desired new type. 1443 * <p> 1444 * If the original type and new type are equal, returns target. 1445 * <p> 1446 * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType}, 1447 * and some additional conversions are also applied if those conversions fail. 1448 * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied 1449 * if possible, before or instead of any conversions done by {@code asType}: 1450 * <ul> 1451 * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type, 1452 * then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast. 1453 * (This treatment of interfaces follows the usage of the bytecode verifier.) 1454 * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive, 1455 * the boolean is converted to a byte value, 1 for true, 0 for false. 1456 * (This treatment follows the usage of the bytecode verifier.) 1457 * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive, 1458 * <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5), 1459 * and the low order bit of the result is tested, as if by {@code (x & 1) != 0}. 1460 * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean, 1461 * then a Java casting conversion (JLS 5.5) is applied. 1462 * (Specifically, <em>T0</em> will convert to <em>T1</em> by 1463 * widening and/or narrowing.) 1464 * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing 1465 * conversion will be applied at runtime, possibly followed 1466 * by a Java casting conversion (JLS 5.5) on the primitive value, 1467 * possibly followed by a conversion from byte to boolean by testing 1468 * the low-order bit. 1469 * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, 1470 * and if the reference is null at runtime, a zero value is introduced. 1471 * </ul> 1472 * @param target the method handle to invoke after arguments are retyped 1473 * @param newType the expected type of the new method handle 1474 * @return a method handle which delegates to the target after performing 1475 * any necessary argument conversions, and arranges for any 1476 * necessary return value conversions 1477 * @throws NullPointerException if either argument is null 1478 * @throws WrongMethodTypeException if the conversion cannot be made 1479 * @see MethodHandle#asType 1480 */ 1481 public static 1482 MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { 1483 if (!target.type().isCastableTo(newType)) { 1484 throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType); 1485 } 1486 return MethodHandleImpl.makePairwiseConvert(target, newType, 2); 1487 } 1488 1489 /** 1490 * Produces a method handle which adapts the calling sequence of the 1491 * given method handle to a new type, by reordering the arguments. 1492 * The resulting method handle is guaranteed to report a type 1493 * which is equal to the desired new type. 1494 * <p> 1495 * The given array controls the reordering. 1496 * Call {@code #I} the number of incoming parameters (the value 1497 * {@code newType.parameterCount()}, and call {@code #O} the number 1498 * of outgoing parameters (the value {@code target.type().parameterCount()}). 1499 * Then the length of the reordering array must be {@code #O}, 1500 * and each element must be a non-negative number less than {@code #I}. 1501 * For every {@code N} less than {@code #O}, the {@code N}-th 1502 * outgoing argument will be taken from the {@code I}-th incoming 1503 * argument, where {@code I} is {@code reorder[N]}. 1504 * <p> 1505 * No argument or return value conversions are applied. 1506 * The type of each incoming argument, as determined by {@code newType}, 1507 * must be identical to the type of the corresponding outgoing parameter 1508 * or parameters in the target method handle. 1509 * The return type of {@code newType} must be identical to the return 1510 * type of the original target. 1511 * <p> 1512 * The reordering array need not specify an actual permutation. 1513 * An incoming argument will be duplicated if its index appears 1514 * more than once in the array, and an incoming argument will be dropped 1515 * if its index does not appear in the array. 1516 * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, 1517 * incoming arguments which are not mentioned in the reordering array 1518 * are may be any type, as determined only by {@code newType}. 1519 * <blockquote><pre> 1520 import static java.lang.invoke.MethodHandles.*; 1521 import static java.lang.invoke.MethodType.*; 1522 ... 1523 MethodType intfn1 = methodType(int.class, int.class); 1524 MethodType intfn2 = methodType(int.class, int.class, int.class); 1525 MethodHandle sub = ... {int x, int y => x-y} ...; 1526 assert(sub.type().equals(intfn2)); 1527 MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1); 1528 MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0); 1529 assert((int)rsub.invokeExact(1, 100) == 99); 1530 MethodHandle add = ... {int x, int y => x+y} ...; 1531 assert(add.type().equals(intfn2)); 1532 MethodHandle twice = permuteArguments(add, intfn1, 0, 0); 1533 assert(twice.type().equals(intfn1)); 1534 assert((int)twice.invokeExact(21) == 42); 1535 * </pre></blockquote> 1536 * @param target the method handle to invoke after arguments are reordered 1537 * @param newType the expected type of the new method handle 1538 * @param reorder an index array which controls the reordering 1539 * @return a method handle which delegates to the target after it 1540 * drops unused arguments and moves and/or duplicates the other arguments 1541 * @throws NullPointerException if any argument is null 1542 * @throws IllegalArgumentException if the index array length is not equal to 1543 * the arity of the target, or if any index array element 1544 * not a valid index for a parameter of {@code newType}, 1545 * or if two corresponding parameter types in 1546 * {@code target.type()} and {@code newType} are not identical, 1547 */ 1548 public static 1549 MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { 1550 checkReorder(reorder, newType, target.type()); 1551 return target.permuteArguments(newType, reorder); 1552 } 1553 1554 private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) { 1555 if (newType.returnType() != oldType.returnType()) 1556 throw newIllegalArgumentException("return types do not match", 1557 oldType, newType); 1558 if (reorder.length == oldType.parameterCount()) { 1559 int limit = newType.parameterCount(); 1560 boolean bad = false; 1561 for (int j = 0; j < reorder.length; j++) { 1562 int i = reorder[j]; 1563 if (i < 0 || i >= limit) { 1564 bad = true; break; 1565 } 1566 Class<?> src = newType.parameterType(i); 1567 Class<?> dst = oldType.parameterType(j); 1568 if (src != dst) 1569 throw newIllegalArgumentException("parameter types do not match after reorder", 1570 oldType, newType); 1571 } 1572 if (!bad) return; 1573 } 1574 throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); 1575 } 1576 1577 /** 1578 * Produces a method handle of the requested return type which returns the given 1579 * constant value every time it is invoked. 1580 * <p> 1581 * Before the method handle is returned, the passed-in value is converted to the requested type. 1582 * If the requested type is primitive, widening primitive conversions are attempted, 1583 * else reference conversions are attempted. 1584 * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}. 1585 * @param type the return type of the desired method handle 1586 * @param value the value to return 1587 * @return a method handle of the given return type and no arguments, which always returns the given value 1588 * @throws NullPointerException if the {@code type} argument is null 1589 * @throws ClassCastException if the value cannot be converted to the required return type 1590 * @throws IllegalArgumentException if the given type is {@code void.class} 1591 */ 1592 public static 1593 MethodHandle constant(Class<?> type, Object value) { 1594 if (type.isPrimitive()) { 1595 if (type == void.class) 1596 throw newIllegalArgumentException("void type"); 1597 Wrapper w = Wrapper.forPrimitiveType(type); 1598 return insertArguments(identity(type), 0, w.convert(value, type)); 1599 } else { 1600 return identity(type).bindTo(type.cast(value)); 1601 } 1602 } 1603 1604 /** 1605 * Produces a method handle which returns its sole argument when invoked. 1606 * @param type the type of the sole parameter and return value of the desired method handle 1607 * @return a unary method handle which accepts and returns the given type 1608 * @throws NullPointerException if the argument is null 1609 * @throws IllegalArgumentException if the given type is {@code void.class} 1610 */ 1611 public static 1612 MethodHandle identity(Class<?> type) { 1613 if (type == void.class) 1614 throw newIllegalArgumentException("void type"); 1615 else if (type == Object.class) 1616 return ValueConversions.identity(); 1617 else if (type.isPrimitive()) 1618 return ValueConversions.identity(Wrapper.forPrimitiveType(type)); 1619 else 1620 return MethodHandleImpl.makeReferenceIdentity(type); 1621 } 1622 1623 /** 1624 * Provides a target method handle with one or more <em>bound arguments</em> 1625 * in advance of the method handle's invocation. 1626 * The formal parameters to the target corresponding to the bound 1627 * arguments are called <em>bound parameters</em>. 1628 * Returns a new method handle which saves away the bound arguments. 1629 * When it is invoked, it receives arguments for any non-bound parameters, 1630 * binds the saved arguments to their corresponding parameters, 1631 * and calls the original target. 1632 * <p> 1633 * The type of the new method handle will drop the types for the bound 1634 * parameters from the original target type, since the new method handle 1635 * will no longer require those arguments to be supplied by its callers. 1636 * <p> 1637 * Each given argument object must match the corresponding bound parameter type. 1638 * If a bound parameter type is a primitive, the argument object 1639 * must be a wrapper, and will be unboxed to produce the primitive value. 1640 * <p> 1641 * The {@code pos} argument selects which parameters are to be bound. 1642 * It may range between zero and <i>N-L</i> (inclusively), 1643 * where <i>N</i> is the arity of the target method handle 1644 * and <i>L</i> is the length of the values array. 1645 * @param target the method handle to invoke after the argument is inserted 1646 * @param pos where to insert the argument (zero for the first) 1647 * @param values the series of arguments to insert 1648 * @return a method handle which inserts an additional argument, 1649 * before calling the original method handle 1650 * @throws NullPointerException if the target or the {@code values} array is null 1651 * @see MethodHandle#bindTo 1652 */ 1653 public static 1654 MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { 1655 int insCount = values.length; 1656 MethodType oldType = target.type(); 1657 int outargs = oldType.parameterCount(); 1658 int inargs = outargs - insCount; 1659 if (inargs < 0) 1660 throw newIllegalArgumentException("too many values to insert"); 1661 if (pos < 0 || pos > inargs) 1662 throw newIllegalArgumentException("no argument type to append"); 1663 MethodHandle result = target; 1664 for (int i = 0; i < insCount; i++) { 1665 Object value = values[i]; 1666 Class<?> ptype = oldType.parameterType(pos+i); 1667 if (ptype.isPrimitive()) { 1668 char btype = 'I'; 1669 Wrapper w = Wrapper.forPrimitiveType(ptype); 1670 switch (w) { 1671 case LONG: btype = 'J'; break; 1672 case FLOAT: btype = 'F'; break; 1673 case DOUBLE: btype = 'D'; break; 1674 } 1675 // perform unboxing and/or primitive conversion 1676 value = w.convert(value, ptype); 1677 result = result.bindArgument(pos, btype, value); 1678 continue; 1679 } 1680 value = ptype.cast(value); // throw CCE if needed 1681 if (pos == 0) { 1682 result = result.bindReceiver(value); 1683 } else { 1684 result = result.bindArgument(pos, 'L', value); 1685 } 1686 } 1687 return result; 1688 } 1689 1690 /** 1691 * Produces a method handle which will discard some dummy arguments 1692 * before calling some other specified <i>target</i> method handle. 1693 * The type of the new method handle will be the same as the target's type, 1694 * except it will also include the dummy argument types, 1695 * at some given position. 1696 * <p> 1697 * The {@code pos} argument may range between zero and <i>N</i>, 1698 * where <i>N</i> is the arity of the target. 1699 * If {@code pos} is zero, the dummy arguments will precede 1700 * the target's real arguments; if {@code pos} is <i>N</i> 1701 * they will come after. 1702 * <p> 1703 * <b>Example:</b> 1704 * <p><blockquote><pre> 1705 import static java.lang.invoke.MethodHandles.*; 1706 import static java.lang.invoke.MethodType.*; 1707 ... 1708 MethodHandle cat = lookup().findVirtual(String.class, 1709 "concat", methodType(String.class, String.class)); 1710 assertEquals("xy", (String) cat.invokeExact("x", "y")); 1711 MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class); 1712 MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2)); 1713 assertEquals(bigType, d0.type()); 1714 assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); 1715 * </pre></blockquote> 1716 * <p> 1717 * This method is also equivalent to the following code: 1718 * <p><blockquote><pre> 1719 * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0])) 1720 * </pre></blockquote> 1721 * @param target the method handle to invoke after the arguments are dropped 1722 * @param valueTypes the type(s) of the argument(s) to drop 1723 * @param pos position of first argument to drop (zero for the leftmost) 1724 * @return a method handle which drops arguments of the given types, 1725 * before calling the original method handle 1726 * @throws NullPointerException if the target is null, 1727 * or if the {@code valueTypes} list or any of its elements is null 1728 * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, 1729 * or if {@code pos} is negative or greater than the arity of the target, 1730 * or if the new method handle's type would have too many parameters 1731 */ 1732 public static 1733 MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { 1734 MethodType oldType = target.type(); // get NPE 1735 int dropped = valueTypes.size(); 1736 MethodType.checkSlotCount(dropped); 1737 if (dropped == 0) return target; 1738 int outargs = oldType.parameterCount(); 1739 int inargs = outargs + dropped; 1740 if (pos < 0 || pos >= inargs) 1741 throw newIllegalArgumentException("no argument type to remove"); 1742 ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList()); 1743 ptypes.addAll(pos, valueTypes); 1744 MethodType newType = MethodType.methodType(oldType.returnType(), ptypes); 1745 return target.dropArguments(newType, pos, dropped); 1746 } 1747 1748 /** 1749 * Produces a method handle which will discard some dummy arguments 1750 * before calling some other specified <i>target</i> method handle. 1751 * The type of the new method handle will be the same as the target's type, 1752 * except it will also include the dummy argument types, 1753 * at some given position. 1754 * <p> 1755 * The {@code pos} argument may range between zero and <i>N</i>, 1756 * where <i>N</i> is the arity of the target. 1757 * If {@code pos} is zero, the dummy arguments will precede 1758 * the target's real arguments; if {@code pos} is <i>N</i> 1759 * they will come after. 1760 * <p> 1761 * <b>Example:</b> 1762 * <p><blockquote><pre> 1763 import static java.lang.invoke.MethodHandles.*; 1764 import static java.lang.invoke.MethodType.*; 1765 ... 1766 MethodHandle cat = lookup().findVirtual(String.class, 1767 "concat", methodType(String.class, String.class)); 1768 assertEquals("xy", (String) cat.invokeExact("x", "y")); 1769 MethodHandle d0 = dropArguments(cat, 0, String.class); 1770 assertEquals("yz", (String) d0.invokeExact("x", "y", "z")); 1771 MethodHandle d1 = dropArguments(cat, 1, String.class); 1772 assertEquals("xz", (String) d1.invokeExact("x", "y", "z")); 1773 MethodHandle d2 = dropArguments(cat, 2, String.class); 1774 assertEquals("xy", (String) d2.invokeExact("x", "y", "z")); 1775 MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); 1776 assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); 1777 * </pre></blockquote> 1778 * <p> 1779 * This method is also equivalent to the following code: 1780 * <p><blockquote><pre> 1781 * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes)) 1782 * </pre></blockquote> 1783 * @param target the method handle to invoke after the arguments are dropped 1784 * @param valueTypes the type(s) of the argument(s) to drop 1785 * @param pos position of first argument to drop (zero for the leftmost) 1786 * @return a method handle which drops arguments of the given types, 1787 * before calling the original method handle 1788 * @throws NullPointerException if the target is null, 1789 * or if the {@code valueTypes} array or any of its elements is null 1790 * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, 1791 * or if {@code pos} is negative or greater than the arity of the target, 1792 * or if the new method handle's type would have too many parameters 1793 */ 1794 public static 1795 MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) { 1796 return dropArguments(target, pos, Arrays.asList(valueTypes)); 1797 } 1798 1799 /** 1800 * Adapts a target method handle by pre-processing 1801 * one or more of its arguments, each with its own unary filter function, 1802 * and then calling the target with each pre-processed argument 1803 * replaced by the result of its corresponding filter function. 1804 * <p> 1805 * The pre-processing is performed by one or more method handles, 1806 * specified in the elements of the {@code filters} array. 1807 * The first element of the filter array corresponds to the {@code pos} 1808 * argument of the target, and so on in sequence. 1809 * <p> 1810 * Null arguments in the array are treated as identity functions, 1811 * and the corresponding arguments left unchanged. 1812 * (If there are no non-null elements in the array, the original target is returned.) 1813 * Each filter is applied to the corresponding argument of the adapter. 1814 * <p> 1815 * If a filter {@code F} applies to the {@code N}th argument of 1816 * the target, then {@code F} must be a method handle which 1817 * takes exactly one argument. The type of {@code F}'s sole argument 1818 * replaces the corresponding argument type of the target 1819 * in the resulting adapted method handle. 1820 * The return type of {@code F} must be identical to the corresponding 1821 * parameter type of the target. 1822 * <p> 1823 * It is an error if there are elements of {@code filters} 1824 * (null or not) 1825 * which do not correspond to argument positions in the target. 1826 * <b>Example:</b> 1827 * <p><blockquote><pre> 1828 import static java.lang.invoke.MethodHandles.*; 1829 import static java.lang.invoke.MethodType.*; 1830 ... 1831 MethodHandle cat = lookup().findVirtual(String.class, 1832 "concat", methodType(String.class, String.class)); 1833 MethodHandle upcase = lookup().findVirtual(String.class, 1834 "toUpperCase", methodType(String.class)); 1835 assertEquals("xy", (String) cat.invokeExact("x", "y")); 1836 MethodHandle f0 = filterArguments(cat, 0, upcase); 1837 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy 1838 MethodHandle f1 = filterArguments(cat, 1, upcase); 1839 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY 1840 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); 1841 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY 1842 * </pre></blockquote> 1843 * <p> Here is pseudocode for the resulting adapter: 1844 * <blockquote><pre> 1845 * V target(P... p, A[i]... a[i], B... b); 1846 * A[i] filter[i](V[i]); 1847 * T adapter(P... p, V[i]... v[i], B... b) { 1848 * return target(p..., f[i](v[i])..., b...); 1849 * } 1850 * </pre></blockquote> 1851 * 1852 * @param target the method handle to invoke after arguments are filtered 1853 * @param pos the position of the first argument to filter 1854 * @param filters method handles to call initially on filtered arguments 1855 * @return method handle which incorporates the specified argument filtering logic 1856 * @throws NullPointerException if the target is null 1857 * or if the {@code filters} array is null 1858 * @throws IllegalArgumentException if a non-null element of {@code filters} 1859 * does not match a corresponding argument type of target as described above, 1860 * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()} 1861 */ 1862 public static 1863 MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { 1864 MethodType targetType = target.type(); 1865 MethodHandle adapter = target; 1866 MethodType adapterType = null; 1867 assert((adapterType = targetType) != null); 1868 int maxPos = targetType.parameterCount(); 1869 if (pos + filters.length > maxPos) 1870 throw newIllegalArgumentException("too many filters"); 1871 int curPos = pos-1; // pre-incremented 1872 for (MethodHandle filter : filters) { 1873 curPos += 1; 1874 if (filter == null) continue; // ignore null elements of filters 1875 adapter = filterArgument(adapter, curPos, filter); 1876 assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null); 1877 } 1878 assert(adapterType.equals(adapter.type())); 1879 return adapter; 1880 } 1881 1882 /*non-public*/ static 1883 MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) { 1884 MethodType targetType = target.type(); 1885 MethodType filterType = filter.type(); 1886 if (filterType.parameterCount() != 1 1887 || filterType.returnType() != targetType.parameterType(pos)) 1888 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); 1889 return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); 1890 } 1891 1892 // FIXME: Make this public in M1. 1893 /*non-public*/ static 1894 MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle collector) { 1895 MethodType targetType = target.type(); 1896 MethodType filterType = collector.type(); 1897 if (filterType.returnType() != void.class && 1898 filterType.returnType() != targetType.parameterType(pos)) 1899 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); 1900 return MethodHandleImpl.makeCollectArguments(target, collector, pos, false); 1901 } 1902 1903 /** 1904 * Adapts a target method handle by post-processing 1905 * its return value (if any) with a filter (another method handle). 1906 * The result of the filter is returned from the adapter. 1907 * <p> 1908 * If the target returns a value, the filter must accept that value as 1909 * its only argument. 1910 * If the target returns void, the filter must accept no arguments. 1911 * <p> 1912 * The return type of the filter 1913 * replaces the return type of the target 1914 * in the resulting adapted method handle. 1915 * The argument type of the filter (if any) must be identical to the 1916 * return type of the target. 1917 * <b>Example:</b> 1918 * <p><blockquote><pre> 1919 import static java.lang.invoke.MethodHandles.*; 1920 import static java.lang.invoke.MethodType.*; 1921 ... 1922 MethodHandle cat = lookup().findVirtual(String.class, 1923 "concat", methodType(String.class, String.class)); 1924 MethodHandle length = lookup().findVirtual(String.class, 1925 "length", methodType(int.class)); 1926 System.out.println((String) cat.invokeExact("x", "y")); // xy 1927 MethodHandle f0 = filterReturnValue(cat, length); 1928 System.out.println((int) f0.invokeExact("x", "y")); // 2 1929 * </pre></blockquote> 1930 * <p> Here is pseudocode for the resulting adapter: 1931 * <blockquote><pre> 1932 * V target(A...); 1933 * T filter(V); 1934 * T adapter(A... a) { 1935 * V v = target(a...); 1936 * return filter(v); 1937 * } 1938 * // and if the target has a void return: 1939 * void target2(A...); 1940 * T filter2(); 1941 * T adapter2(A... a) { 1942 * target2(a...); 1943 * return filter2(); 1944 * } 1945 * // and if the filter has a void return: 1946 * V target3(A...); 1947 * void filter3(V); 1948 * void adapter3(A... a) { 1949 * V v = target3(a...); 1950 * filter3(v); 1951 * } 1952 * </pre></blockquote> 1953 * @param target the method handle to invoke before filtering the return value 1954 * @param filter method handle to call on the return value 1955 * @return method handle which incorporates the specified return value filtering logic 1956 * @throws NullPointerException if either argument is null 1957 * @throws IllegalArgumentException if the argument list of {@code filter} 1958 * does not match the return type of target as described above 1959 */ 1960 public static 1961 MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { 1962 MethodType targetType = target.type(); 1963 MethodType filterType = filter.type(); 1964 Class<?> rtype = targetType.returnType(); 1965 int filterValues = filterType.parameterCount(); 1966 if (filterValues == 0 1967 ? (rtype != void.class) 1968 : (rtype != filterType.parameterType(0))) 1969 throw newIllegalArgumentException("target and filter types do not match", target, filter); 1970 // result = fold( lambda(retval, arg...) { filter(retval) }, 1971 // lambda( arg...) { target(arg...) } ) 1972 return MethodHandleImpl.makeCollectArguments(filter, target, 0, false); 1973 } 1974 1975 /** 1976 * Adapts a target method handle by pre-processing 1977 * some of its arguments, and then calling the target with 1978 * the result of the pre-processing, inserted into the original 1979 * sequence of arguments. 1980 * <p> 1981 * The pre-processing is performed by {@code combiner}, a second method handle. 1982 * Of the arguments passed to the adapter, the first {@code N} arguments 1983 * are copied to the combiner, which is then called. 1984 * (Here, {@code N} is defined as the parameter count of the combiner.) 1985 * After this, control passes to the target, with any result 1986 * from the combiner inserted before the original {@code N} incoming 1987 * arguments. 1988 * <p> 1989 * If the combiner returns a value, the first parameter type of the target 1990 * must be identical with the return type of the combiner, and the next 1991 * {@code N} parameter types of the target must exactly match the parameters 1992 * of the combiner. 1993 * <p> 1994 * If the combiner has a void return, no result will be inserted, 1995 * and the first {@code N} parameter types of the target 1996 * must exactly match the parameters of the combiner. 1997 * <p> 1998 * The resulting adapter is the same type as the target, except that the 1999 * first parameter type is dropped, 2000 * if it corresponds to the result of the combiner. 2001 * <p> 2002 * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments 2003 * that either the combiner or the target does not wish to receive. 2004 * If some of the incoming arguments are destined only for the combiner, 2005 * consider using {@link MethodHandle#asCollector asCollector} instead, since those 2006 * arguments will not need to be live on the stack on entry to the 2007 * target.) 2008 * <b>Example:</b> 2009 * <p><blockquote><pre> 2010 import static java.lang.invoke.MethodHandles.*; 2011 import static java.lang.invoke.MethodType.*; 2012 ... 2013 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class, 2014 "println", methodType(void.class, String.class)) 2015 .bindTo(System.out); 2016 MethodHandle cat = lookup().findVirtual(String.class, 2017 "concat", methodType(String.class, String.class)); 2018 assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); 2019 MethodHandle catTrace = foldArguments(cat, trace); 2020 // also prints "boo": 2021 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); 2022 * </pre></blockquote> 2023 * <p> Here is pseudocode for the resulting adapter: 2024 * <blockquote><pre> 2025 * // there are N arguments in A... 2026 * T target(V, A[N]..., B...); 2027 * V combiner(A...); 2028 * T adapter(A... a, B... b) { 2029 * V v = combiner(a...); 2030 * return target(v, a..., b...); 2031 * } 2032 * // and if the combiner has a void return: 2033 * T target2(A[N]..., B...); 2034 * void combiner2(A...); 2035 * T adapter2(A... a, B... b) { 2036 * combiner2(a...); 2037 * return target2(a..., b...); 2038 * } 2039 * </pre></blockquote> 2040 * @param target the method handle to invoke after arguments are combined 2041 * @param combiner method handle to call initially on the incoming arguments 2042 * @return method handle which incorporates the specified argument folding logic 2043 * @throws NullPointerException if either argument is null 2044 * @throws IllegalArgumentException if {@code combiner}'s return type 2045 * is non-void and not the same as the first argument type of 2046 * the target, or if the initial {@code N} argument types 2047 * of the target 2048 * (skipping one matching the {@code combiner}'s return type) 2049 * are not identical with the argument types of {@code combiner} 2050 */ 2051 public static 2052 MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { 2053 int pos = 0; 2054 MethodType targetType = target.type(); 2055 MethodType combinerType = combiner.type(); 2056 int foldPos = pos; 2057 int foldArgs = combinerType.parameterCount(); 2058 int foldVals = combinerType.returnType() == void.class ? 0 : 1; 2059 int afterInsertPos = foldPos + foldVals; 2060 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs); 2061 if (ok && !(combinerType.parameterList() 2062 .equals(targetType.parameterList().subList(afterInsertPos, 2063 afterInsertPos + foldArgs)))) 2064 ok = false; 2065 if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0))) 2066 ok = false; 2067 if (!ok) 2068 throw misMatchedTypes("target and combiner types", targetType, combinerType); 2069 MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos); 2070 return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true); 2071 } 2072 2073 /** 2074 * Makes a method handle which adapts a target method handle, 2075 * by guarding it with a test, a boolean-valued method handle. 2076 * If the guard fails, a fallback handle is called instead. 2077 * All three method handles must have the same corresponding 2078 * argument and return types, except that the return type 2079 * of the test must be boolean, and the test is allowed 2080 * to have fewer arguments than the other two method handles. 2081 * <p> Here is pseudocode for the resulting adapter: 2082 * <blockquote><pre> 2083 * boolean test(A...); 2084 * T target(A...,B...); 2085 * T fallback(A...,B...); 2086 * T adapter(A... a,B... b) { 2087 * if (test(a...)) 2088 * return target(a..., b...); 2089 * else 2090 * return fallback(a..., b...); 2091 * } 2092 * </pre></blockquote> 2093 * Note that the test arguments ({@code a...} in the pseudocode) cannot 2094 * be modified by execution of the test, and so are passed unchanged 2095 * from the caller to the target or fallback as appropriate. 2096 * @param test method handle used for test, must return boolean 2097 * @param target method handle to call if test passes 2098 * @param fallback method handle to call if test fails 2099 * @return method handle which incorporates the specified if/then/else logic 2100 * @throws NullPointerException if any argument is null 2101 * @throws IllegalArgumentException if {@code test} does not return boolean, 2102 * or if all three method types do not match (with the return 2103 * type of {@code test} changed to match that of the target). 2104 */ 2105 public static 2106 MethodHandle guardWithTest(MethodHandle test, 2107 MethodHandle target, 2108 MethodHandle fallback) { 2109 MethodType gtype = test.type(); 2110 MethodType ttype = target.type(); 2111 MethodType ftype = fallback.type(); 2112 if (!ttype.equals(ftype)) 2113 throw misMatchedTypes("target and fallback types", ttype, ftype); 2114 if (gtype.returnType() != boolean.class) 2115 throw newIllegalArgumentException("guard type is not a predicate "+gtype); 2116 List<Class<?>> targs = ttype.parameterList(); 2117 List<Class<?>> gargs = gtype.parameterList(); 2118 if (!targs.equals(gargs)) { 2119 int gpc = gargs.size(), tpc = targs.size(); 2120 if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs)) 2121 throw misMatchedTypes("target and test types", ttype, gtype); 2122 test = dropArguments(test, gpc, targs.subList(gpc, tpc)); 2123 gtype = test.type(); 2124 } 2125 return MethodHandleImpl.makeGuardWithTest(test, target, fallback); 2126 } 2127 2128 static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) { 2129 return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2); 2130 } 2131 2132 /** 2133 * Makes a method handle which adapts a target method handle, 2134 * by running it inside an exception handler. 2135 * If the target returns normally, the adapter returns that value. 2136 * If an exception matching the specified type is thrown, the fallback 2137 * handle is called instead on the exception, plus the original arguments. 2138 * <p> 2139 * The target and handler must have the same corresponding 2140 * argument and return types, except that handler may omit trailing arguments 2141 * (similarly to the predicate in {@link #guardWithTest guardWithTest}). 2142 * Also, the handler must have an extra leading parameter of {@code exType} or a supertype. 2143 * <p> Here is pseudocode for the resulting adapter: 2144 * <blockquote><pre> 2145 * T target(A..., B...); 2146 * T handler(ExType, A...); 2147 * T adapter(A... a, B... b) { 2148 * try { 2149 * return target(a..., b...); 2150 * } catch (ExType ex) { 2151 * return handler(ex, a...); 2152 * } 2153 * } 2154 * </pre></blockquote> 2155 * Note that the saved arguments ({@code a...} in the pseudocode) cannot 2156 * be modified by execution of the target, and so are passed unchanged 2157 * from the caller to the handler, if the handler is invoked. 2158 * <p> 2159 * The target and handler must return the same type, even if the handler 2160 * always throws. (This might happen, for instance, because the handler 2161 * is simulating a {@code finally} clause). 2162 * To create such a throwing handler, compose the handler creation logic 2163 * with {@link #throwException throwException}, 2164 * in order to create a method handle of the correct return type. 2165 * @param target method handle to call 2166 * @param exType the type of exception which the handler will catch 2167 * @param handler method handle to call if a matching exception is thrown 2168 * @return method handle which incorporates the specified try/catch logic 2169 * @throws NullPointerException if any argument is null 2170 * @throws IllegalArgumentException if {@code handler} does not accept 2171 * the given exception type, or if the method handle types do 2172 * not match in their return types and their 2173 * corresponding parameters 2174 */ 2175 public static 2176 MethodHandle catchException(MethodHandle target, 2177 Class<? extends Throwable> exType, 2178 MethodHandle handler) { 2179 MethodType ttype = target.type(); 2180 MethodType htype = handler.type(); 2181 if (htype.parameterCount() < 1 || 2182 !htype.parameterType(0).isAssignableFrom(exType)) 2183 throw newIllegalArgumentException("handler does not accept exception type "+exType); 2184 if (htype.returnType() != ttype.returnType()) 2185 throw misMatchedTypes("target and handler return types", ttype, htype); 2186 List<Class<?>> targs = ttype.parameterList(); 2187 List<Class<?>> hargs = htype.parameterList(); 2188 hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler 2189 if (!targs.equals(hargs)) { 2190 int hpc = hargs.size(), tpc = targs.size(); 2191 if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs)) 2192 throw misMatchedTypes("target and handler types", ttype, htype); 2193 handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc)); 2194 htype = handler.type(); 2195 } 2196 return MethodHandleImpl.makeGuardWithCatch(target, exType, handler); 2197 } 2198 2199 /** 2200 * Produces a method handle which will throw exceptions of the given {@code exType}. 2201 * The method handle will accept a single argument of {@code exType}, 2202 * and immediately throw it as an exception. 2203 * The method type will nominally specify a return of {@code returnType}. 2204 * The return type may be anything convenient: It doesn't matter to the 2205 * method handle's behavior, since it will never return normally. 2206 * @return method handle which can throw the given exceptions 2207 * @throws NullPointerException if either argument is null 2208 */ 2209 public static 2210 MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) { 2211 if (!Throwable.class.isAssignableFrom(exType)) 2212 throw new ClassCastException(exType.getName()); 2213 return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType)); 2214 } 2215 }