1 /* 2 * Copyright (c) 2008, 2016, 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 java.util.List; 30 import java.util.Arrays; 31 import java.util.ArrayList; 32 import java.util.NoSuchElementException; 33 34 import dalvik.system.VMStack; 35 import sun.invoke.util.VerifyAccess; 36 import sun.invoke.util.Wrapper; 37 import static java.lang.invoke.MethodHandleStatics.*; 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 * </ul> 47 * <p> 48 * @author John Rose, JSR 292 EG 49 * @since 1.7 50 */ 51 public class MethodHandles { 52 MethodHandles()53 private MethodHandles() { } // do not instantiate 54 55 // Android-changed: We do not use MemberName / MethodHandleImpl. 56 // 57 // private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); 58 // static { MethodHandleImpl.initStatics(); } 59 // See IMPL_LOOKUP below. 60 61 //// Method handle creation from ordinary methods. 62 63 /** 64 * Returns a {@link Lookup lookup object} with 65 * full capabilities to emulate all supported bytecode behaviors of the caller. 66 * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller. 67 * Factory methods on the lookup object can create 68 * <a href="MethodHandleInfo.html#directmh">direct method handles</a> 69 * for any member that the caller has access to via bytecodes, 70 * including protected and private fields and methods. 71 * This lookup object is a <em>capability</em> which may be delegated to trusted agents. 72 * Do not store it in place where untrusted code can access it. 73 * <p> 74 * This method is caller sensitive, which means that it may return different 75 * values to different callers. 76 * <p> 77 * For any given caller class {@code C}, the lookup object returned by this call 78 * has equivalent capabilities to any lookup object 79 * supplied by the JVM to the bootstrap method of an 80 * <a href="package-summary.html#indyinsn">invokedynamic instruction</a> 81 * executing in the same caller class {@code C}. 82 * @return a lookup object for the caller of this method, with private access 83 */ 84 // Android-changed: Remove caller sensitive. 85 // @CallerSensitive lookup()86 public static Lookup lookup() { 87 // Android-changed: Do not use Reflection.getCallerClass(). 88 return new Lookup(VMStack.getStackClass1()); 89 } 90 91 /** 92 * Returns a {@link Lookup lookup object} which is trusted minimally. 93 * It can only be used to create method handles to 94 * publicly accessible fields and methods. 95 * <p> 96 * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} 97 * of this lookup object will be {@link java.lang.Object}. 98 * 99 * <p style="font-size:smaller;"> 100 * <em>Discussion:</em> 101 * The lookup class can be changed to any other class {@code C} using an expression of the form 102 * {@link Lookup#in publicLookup().in(C.class)}. 103 * Since all classes have equal access to public names, 104 * such a change would confer no new access rights. 105 * A public lookup object is always subject to 106 * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. 107 * Also, it cannot access 108 * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. 109 * @return a lookup object which is trusted minimally 110 */ publicLookup()111 public static Lookup publicLookup() { 112 return Lookup.PUBLIC_LOOKUP; 113 } 114 115 /** 116 * Performs an unchecked "crack" of a 117 * <a href="MethodHandleInfo.html#directmh">direct method handle</a>. 118 * The result is as if the user had obtained a lookup object capable enough 119 * to crack the target method handle, called 120 * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect} 121 * on the target to obtain its symbolic reference, and then called 122 * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs} 123 * to resolve the symbolic reference to a member. 124 * <p> 125 * If there is a security manager, its {@code checkPermission} method 126 * is called with a {@code ReflectPermission("suppressAccessChecks")} permission. 127 * @param <T> the desired type of the result, either {@link Member} or a subtype 128 * @param target a direct method handle to crack into symbolic reference components 129 * @param expected a class object representing the desired result type {@code T} 130 * @return a reference to the method, constructor, or field object 131 * @exception SecurityException if the caller is not privileged to call {@code setAccessible} 132 * @exception NullPointerException if either argument is {@code null} 133 * @exception IllegalArgumentException if the target is not a direct method handle 134 * @exception ClassCastException if the member is not of the expected type 135 * @since 1.8 136 */ 137 public static <T extends Member> T reflectAs(Class<T> expected, MethodHandle target)138 reflectAs(Class<T> expected, MethodHandle target) { 139 MethodHandleImpl directTarget = getMethodHandleImpl(target); 140 // Given that this is specified to be an "unchecked" crack, we can directly allocate 141 // a member from the underlying ArtField / Method and bypass all associated access checks. 142 return expected.cast(directTarget.getMemberInternal()); 143 } 144 145 /** 146 * A <em>lookup object</em> is a factory for creating method handles, 147 * when the creation requires access checking. 148 * Method handles do not perform 149 * access checks when they are called, but rather when they are created. 150 * Therefore, method handle access 151 * restrictions must be enforced when a method handle is created. 152 * The caller class against which those restrictions are enforced 153 * is known as the {@linkplain #lookupClass lookup class}. 154 * <p> 155 * A lookup class which needs to create method handles will call 156 * {@link #lookup MethodHandles.lookup} to create a factory for itself. 157 * When the {@code Lookup} factory object is created, the identity of the lookup class is 158 * determined, and securely stored in the {@code Lookup} object. 159 * The lookup class (or its delegates) may then use factory methods 160 * on the {@code Lookup} object to create method handles for access-checked members. 161 * This includes all methods, constructors, and fields which are allowed to the lookup class, 162 * even private ones. 163 * 164 * <h1><a name="lookups"></a>Lookup Factory Methods</h1> 165 * The factory methods on a {@code Lookup} object correspond to all major 166 * use cases for methods, constructors, and fields. 167 * Each method handle created by a factory method is the functional 168 * equivalent of a particular <em>bytecode behavior</em>. 169 * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.) 170 * Here is a summary of the correspondence between these factory methods and 171 * the behavior the resulting method handles: 172 * <table border=1 cellpadding=5 summary="lookup method behaviors"> 173 * <tr> 174 * <th><a name="equiv"></a>lookup expression</th> 175 * <th>member</th> 176 * <th>bytecode behavior</th> 177 * </tr> 178 * <tr> 179 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> 180 * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td> 181 * </tr> 182 * <tr> 183 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td> 184 * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td> 185 * </tr> 186 * <tr> 187 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td> 188 * <td>{@code FT f;}</td><td>{@code this.f = x;}</td> 189 * </tr> 190 * <tr> 191 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td> 192 * <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td> 193 * </tr> 194 * <tr> 195 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td> 196 * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td> 197 * </tr> 198 * <tr> 199 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td> 200 * <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td> 201 * </tr> 202 * <tr> 203 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td> 204 * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td> 205 * </tr> 206 * <tr> 207 * <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td> 208 * <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td> 209 * </tr> 210 * <tr> 211 * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td> 212 * <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td> 213 * </tr> 214 * <tr> 215 * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td> 216 * <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td> 217 * </tr> 218 * <tr> 219 * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> 220 * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td> 221 * </tr> 222 * <tr> 223 * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td> 224 * <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td> 225 * </tr> 226 * <tr> 227 * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> 228 * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td> 229 * </tr> 230 * </table> 231 * 232 * Here, the type {@code C} is the class or interface being searched for a member, 233 * documented as a parameter named {@code refc} in the lookup methods. 234 * The method type {@code MT} is composed from the return type {@code T} 235 * and the sequence of argument types {@code A*}. 236 * The constructor also has a sequence of argument types {@code A*} and 237 * is deemed to return the newly-created object of type {@code C}. 238 * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. 239 * The formal parameter {@code this} stands for the self-reference of type {@code C}; 240 * if it is present, it is always the leading argument to the method handle invocation. 241 * (In the case of some {@code protected} members, {@code this} may be 242 * restricted in type to the lookup class; see below.) 243 * The name {@code arg} stands for all the other method handle arguments. 244 * In the code examples for the Core Reflection API, the name {@code thisOrNull} 245 * stands for a null reference if the accessed method or field is static, 246 * and {@code this} otherwise. 247 * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand 248 * for reflective objects corresponding to the given members. 249 * <p> 250 * In cases where the given member is of variable arity (i.e., a method or constructor) 251 * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}. 252 * In all other cases, the returned method handle will be of fixed arity. 253 * <p style="font-size:smaller;"> 254 * <em>Discussion:</em> 255 * The equivalence between looked-up method handles and underlying 256 * class members and bytecode behaviors 257 * can break down in a few ways: 258 * <ul style="font-size:smaller;"> 259 * <li>If {@code C} is not symbolically accessible from the lookup class's loader, 260 * the lookup can still succeed, even when there is no equivalent 261 * Java expression or bytecoded constant. 262 * <li>Likewise, if {@code T} or {@code MT} 263 * is not symbolically accessible from the lookup class's loader, 264 * the lookup can still succeed. 265 * For example, lookups for {@code MethodHandle.invokeExact} and 266 * {@code MethodHandle.invoke} will always succeed, regardless of requested type. 267 * <li>If there is a security manager installed, it can forbid the lookup 268 * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>). 269 * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle} 270 * constant is not subject to security manager checks. 271 * <li>If the looked-up method has a 272 * <a href="MethodHandle.html#maxarity">very large arity</a>, 273 * the method handle creation may fail, due to the method handle 274 * type having too many parameters. 275 * </ul> 276 * 277 * <h1><a name="access"></a>Access checking</h1> 278 * Access checks are applied in the factory methods of {@code Lookup}, 279 * when a method handle is created. 280 * This is a key difference from the Core Reflection API, since 281 * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} 282 * performs access checking against every caller, on every call. 283 * <p> 284 * All access checks start from a {@code Lookup} object, which 285 * compares its recorded lookup class against all requests to 286 * create method handles. 287 * A single {@code Lookup} object can be used to create any number 288 * of access-checked method handles, all checked against a single 289 * lookup class. 290 * <p> 291 * A {@code Lookup} object can be shared with other trusted code, 292 * such as a metaobject protocol. 293 * A shared {@code Lookup} object delegates the capability 294 * to create method handles on private members of the lookup class. 295 * Even if privileged code uses the {@code Lookup} object, 296 * the access checking is confined to the privileges of the 297 * original lookup class. 298 * <p> 299 * A lookup can fail, because 300 * the containing class is not accessible to the lookup class, or 301 * because the desired class member is missing, or because the 302 * desired class member is not accessible to the lookup class, or 303 * because the lookup object is not trusted enough to access the member. 304 * In any of these cases, a {@code ReflectiveOperationException} will be 305 * thrown from the attempted lookup. The exact class will be one of 306 * the following: 307 * <ul> 308 * <li>NoSuchMethodException — if a method is requested but does not exist 309 * <li>NoSuchFieldException — if a field is requested but does not exist 310 * <li>IllegalAccessException — if the member exists but an access check fails 311 * </ul> 312 * <p> 313 * In general, the conditions under which a method handle may be 314 * looked up for a method {@code M} are no more restrictive than the conditions 315 * under which the lookup class could have compiled, verified, and resolved a call to {@code M}. 316 * Where the JVM would raise exceptions like {@code NoSuchMethodError}, 317 * a method handle lookup will generally raise a corresponding 318 * checked exception, such as {@code NoSuchMethodException}. 319 * And the effect of invoking the method handle resulting from the lookup 320 * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a> 321 * to executing the compiled, verified, and resolved call to {@code M}. 322 * The same point is true of fields and constructors. 323 * <p style="font-size:smaller;"> 324 * <em>Discussion:</em> 325 * Access checks only apply to named and reflected methods, 326 * constructors, and fields. 327 * Other method handle creation methods, such as 328 * {@link MethodHandle#asType MethodHandle.asType}, 329 * do not require any access checks, and are used 330 * independently of any {@code Lookup} object. 331 * <p> 332 * If the desired member is {@code protected}, the usual JVM rules apply, 333 * including the requirement that the lookup class must be either be in the 334 * same package as the desired member, or must inherit that member. 335 * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) 336 * In addition, if the desired member is a non-static field or method 337 * in a different package, the resulting method handle may only be applied 338 * to objects of the lookup class or one of its subclasses. 339 * This requirement is enforced by narrowing the type of the leading 340 * {@code this} parameter from {@code C} 341 * (which will necessarily be a superclass of the lookup class) 342 * to the lookup class itself. 343 * <p> 344 * The JVM imposes a similar requirement on {@code invokespecial} instruction, 345 * that the receiver argument must match both the resolved method <em>and</em> 346 * the current class. Again, this requirement is enforced by narrowing the 347 * type of the leading parameter to the resulting method handle. 348 * (See the Java Virtual Machine Specification, section 4.10.1.9.) 349 * <p> 350 * The JVM represents constructors and static initializer blocks as internal methods 351 * with special names ({@code "<init>"} and {@code "<clinit>"}). 352 * The internal syntax of invocation instructions allows them to refer to such internal 353 * methods as if they were normal methods, but the JVM bytecode verifier rejects them. 354 * A lookup of such an internal method will produce a {@code NoSuchMethodException}. 355 * <p> 356 * In some cases, access between nested classes is obtained by the Java compiler by creating 357 * an wrapper method to access a private method of another class 358 * in the same top-level declaration. 359 * For example, a nested class {@code C.D} 360 * can access private members within other related classes such as 361 * {@code C}, {@code C.D.E}, or {@code C.B}, 362 * but the Java compiler may need to generate wrapper methods in 363 * those related classes. In such cases, a {@code Lookup} object on 364 * {@code C.E} would be unable to those private members. 365 * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, 366 * which can transform a lookup on {@code C.E} into one on any of those other 367 * classes, without special elevation of privilege. 368 * <p> 369 * The accesses permitted to a given lookup object may be limited, 370 * according to its set of {@link #lookupModes lookupModes}, 371 * to a subset of members normally accessible to the lookup class. 372 * For example, the {@link #publicLookup publicLookup} 373 * method produces a lookup object which is only allowed to access 374 * public members in public classes. 375 * The caller sensitive method {@link #lookup lookup} 376 * produces a lookup object with full capabilities relative to 377 * its caller class, to emulate all supported bytecode behaviors. 378 * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object 379 * with fewer access modes than the original lookup object. 380 * 381 * <p style="font-size:smaller;"> 382 * <a name="privacc"></a> 383 * <em>Discussion of private access:</em> 384 * We say that a lookup has <em>private access</em> 385 * if its {@linkplain #lookupModes lookup modes} 386 * include the possibility of accessing {@code private} members. 387 * As documented in the relevant methods elsewhere, 388 * only lookups with private access possess the following capabilities: 389 * <ul style="font-size:smaller;"> 390 * <li>access private fields, methods, and constructors of the lookup class 391 * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods, 392 * such as {@code Class.forName} 393 * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions 394 * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a> 395 * for classes accessible to the lookup class 396 * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes 397 * within the same package member 398 * </ul> 399 * <p style="font-size:smaller;"> 400 * Each of these permissions is a consequence of the fact that a lookup object 401 * with private access can be securely traced back to an originating class, 402 * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions 403 * can be reliably determined and emulated by method handles. 404 * 405 * <h1><a name="secmgr"></a>Security manager interactions</h1> 406 * Although bytecode instructions can only refer to classes in 407 * a related class loader, this API can search for methods in any 408 * class, as long as a reference to its {@code Class} object is 409 * available. Such cross-loader references are also possible with the 410 * Core Reflection API, and are impossible to bytecode instructions 411 * such as {@code invokestatic} or {@code getfield}. 412 * There is a {@linkplain java.lang.SecurityManager security manager API} 413 * to allow applications to check such cross-loader references. 414 * These checks apply to both the {@code MethodHandles.Lookup} API 415 * and the Core Reflection API 416 * (as found on {@link java.lang.Class Class}). 417 * <p> 418 * If a security manager is present, member lookups are subject to 419 * additional checks. 420 * From one to three calls are made to the security manager. 421 * Any of these calls can refuse access by throwing a 422 * {@link java.lang.SecurityException SecurityException}. 423 * Define {@code smgr} as the security manager, 424 * {@code lookc} as the lookup class of the current lookup object, 425 * {@code refc} as the containing class in which the member 426 * is being sought, and {@code defc} as the class in which the 427 * member is actually defined. 428 * The value {@code lookc} is defined as <em>not present</em> 429 * if the current lookup object does not have 430 * <a href="MethodHandles.Lookup.html#privacc">private access</a>. 431 * The calls are made according to the following rules: 432 * <ul> 433 * <li><b>Step 1:</b> 434 * If {@code lookc} is not present, or if its class loader is not 435 * the same as or an ancestor of the class loader of {@code refc}, 436 * then {@link SecurityManager#checkPackageAccess 437 * smgr.checkPackageAccess(refcPkg)} is called, 438 * where {@code refcPkg} is the package of {@code refc}. 439 * <li><b>Step 2:</b> 440 * If the retrieved member is not public and 441 * {@code lookc} is not present, then 442 * {@link SecurityManager#checkPermission smgr.checkPermission} 443 * with {@code RuntimePermission("accessDeclaredMembers")} is called. 444 * <li><b>Step 3:</b> 445 * If the retrieved member is not public, 446 * and if {@code lookc} is not present, 447 * and if {@code defc} and {@code refc} are different, 448 * then {@link SecurityManager#checkPackageAccess 449 * smgr.checkPackageAccess(defcPkg)} is called, 450 * where {@code defcPkg} is the package of {@code defc}. 451 * </ul> 452 * Security checks are performed after other access checks have passed. 453 * Therefore, the above rules presuppose a member that is public, 454 * or else that is being accessed from a lookup class that has 455 * rights to access the member. 456 * 457 * <h1><a name="callsens"></a>Caller sensitive methods</h1> 458 * A small number of Java methods have a special property called caller sensitivity. 459 * A <em>caller-sensitive</em> method can behave differently depending on the 460 * identity of its immediate caller. 461 * <p> 462 * If a method handle for a caller-sensitive method is requested, 463 * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply, 464 * but they take account of the lookup class in a special way. 465 * The resulting method handle behaves as if it were called 466 * from an instruction contained in the lookup class, 467 * so that the caller-sensitive method detects the lookup class. 468 * (By contrast, the invoker of the method handle is disregarded.) 469 * Thus, in the case of caller-sensitive methods, 470 * different lookup classes may give rise to 471 * differently behaving method handles. 472 * <p> 473 * In cases where the lookup object is 474 * {@link #publicLookup publicLookup()}, 475 * or some other lookup object without 476 * <a href="MethodHandles.Lookup.html#privacc">private access</a>, 477 * the lookup class is disregarded. 478 * In such cases, no caller-sensitive method handle can be created, 479 * access is forbidden, and the lookup fails with an 480 * {@code IllegalAccessException}. 481 * <p style="font-size:smaller;"> 482 * <em>Discussion:</em> 483 * For example, the caller-sensitive method 484 * {@link java.lang.Class#forName(String) Class.forName(x)} 485 * can return varying classes or throw varying exceptions, 486 * depending on the class loader of the class that calls it. 487 * A public lookup of {@code Class.forName} will fail, because 488 * there is no reasonable way to determine its bytecode behavior. 489 * <p style="font-size:smaller;"> 490 * If an application caches method handles for broad sharing, 491 * it should use {@code publicLookup()} to create them. 492 * If there is a lookup of {@code Class.forName}, it will fail, 493 * and the application must take appropriate action in that case. 494 * It may be that a later lookup, perhaps during the invocation of a 495 * bootstrap method, can incorporate the specific identity 496 * of the caller, making the method accessible. 497 * <p style="font-size:smaller;"> 498 * The function {@code MethodHandles.lookup} is caller sensitive 499 * so that there can be a secure foundation for lookups. 500 * Nearly all other methods in the JSR 292 API rely on lookup 501 * objects to check access requests. 502 */ 503 // Android-changed: Change link targets from MethodHandles#[public]Lookup to 504 // #[public]Lookup to work around complaints from javadoc. 505 public static final 506 class Lookup { 507 /** The class on behalf of whom the lookup is being performed. */ 508 /* @NonNull */ private final Class<?> lookupClass; 509 510 /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */ 511 private final int allowedModes; 512 513 /** A single-bit mask representing {@code public} access, 514 * which may contribute to the result of {@link #lookupModes lookupModes}. 515 * The value, {@code 0x01}, happens to be the same as the value of the 516 * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}. 517 */ 518 public static final int PUBLIC = Modifier.PUBLIC; 519 520 /** A single-bit mask representing {@code private} access, 521 * which may contribute to the result of {@link #lookupModes lookupModes}. 522 * The value, {@code 0x02}, happens to be the same as the value of the 523 * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}. 524 */ 525 public static final int PRIVATE = Modifier.PRIVATE; 526 527 /** A single-bit mask representing {@code protected} access, 528 * which may contribute to the result of {@link #lookupModes lookupModes}. 529 * The value, {@code 0x04}, happens to be the same as the value of the 530 * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}. 531 */ 532 public static final int PROTECTED = Modifier.PROTECTED; 533 534 /** A single-bit mask representing {@code package} access (default access), 535 * which may contribute to the result of {@link #lookupModes lookupModes}. 536 * The value is {@code 0x08}, which does not correspond meaningfully to 537 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. 538 */ 539 public static final int PACKAGE = Modifier.STATIC; 540 541 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE); 542 543 // Android-note: Android has no notion of a trusted lookup. If required, such lookups 544 // are performed by the runtime. As a result, we always use lookupClass, which will always 545 // be non-null in our implementation. 546 // 547 // private static final int TRUSTED = -1; 548 fixmods(int mods)549 private static int fixmods(int mods) { 550 mods &= (ALL_MODES - PACKAGE); 551 return (mods != 0) ? mods : PACKAGE; 552 } 553 554 /** Tells which class is performing the lookup. It is this class against 555 * which checks are performed for visibility and access permissions. 556 * <p> 557 * The class implies a maximum level of access permission, 558 * but the permissions may be additionally limited by the bitmask 559 * {@link #lookupModes lookupModes}, which controls whether non-public members 560 * can be accessed. 561 * @return the lookup class, on behalf of which this lookup object finds members 562 */ lookupClass()563 public Class<?> lookupClass() { 564 return lookupClass; 565 } 566 567 /** Tells which access-protection classes of members this lookup object can produce. 568 * The result is a bit-mask of the bits 569 * {@linkplain #PUBLIC PUBLIC (0x01)}, 570 * {@linkplain #PRIVATE PRIVATE (0x02)}, 571 * {@linkplain #PROTECTED PROTECTED (0x04)}, 572 * and {@linkplain #PACKAGE PACKAGE (0x08)}. 573 * <p> 574 * A freshly-created lookup object 575 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} 576 * has all possible bits set, since the caller class can access all its own members. 577 * A lookup object on a new lookup class 578 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} 579 * may have some mode bits set to zero. 580 * The purpose of this is to restrict access via the new lookup object, 581 * so that it can access only names which can be reached by the original 582 * lookup object, and also by the new lookup class. 583 * @return the lookup modes, which limit the kinds of access performed by this lookup object 584 */ lookupModes()585 public int lookupModes() { 586 return allowedModes & ALL_MODES; 587 } 588 589 /** Embody the current class (the lookupClass) as a lookup class 590 * for method handle creation. 591 * Must be called by from a method in this package, 592 * which in turn is called by a method not in this package. 593 */ Lookup(Class<?> lookupClass)594 Lookup(Class<?> lookupClass) { 595 this(lookupClass, ALL_MODES); 596 // make sure we haven't accidentally picked up a privileged class: 597 checkUnprivilegedlookupClass(lookupClass, ALL_MODES); 598 } 599 Lookup(Class<?> lookupClass, int allowedModes)600 private Lookup(Class<?> lookupClass, int allowedModes) { 601 this.lookupClass = lookupClass; 602 this.allowedModes = allowedModes; 603 } 604 605 /** 606 * Creates a lookup on the specified new lookup class. 607 * The resulting object will report the specified 608 * class as its own {@link #lookupClass lookupClass}. 609 * <p> 610 * However, the resulting {@code Lookup} object is guaranteed 611 * to have no more access capabilities than the original. 612 * In particular, access capabilities can be lost as follows:<ul> 613 * <li>If the new lookup class differs from the old one, 614 * protected members will not be accessible by virtue of inheritance. 615 * (Protected members may continue to be accessible because of package sharing.) 616 * <li>If the new lookup class is in a different package 617 * than the old one, protected and default (package) members will not be accessible. 618 * <li>If the new lookup class is not within the same package member 619 * as the old one, private members will not be accessible. 620 * <li>If the new lookup class is not accessible to the old lookup class, 621 * then no members, not even public members, will be accessible. 622 * (In all other cases, public members will continue to be accessible.) 623 * </ul> 624 * 625 * @param requestedLookupClass the desired lookup class for the new lookup object 626 * @return a lookup object which reports the desired lookup class 627 * @throws NullPointerException if the argument is null 628 */ in(Class<?> requestedLookupClass)629 public Lookup in(Class<?> requestedLookupClass) { 630 requestedLookupClass.getClass(); // null check 631 // Android-changed: There's no notion of a trusted lookup. 632 // if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all 633 // return new Lookup(requestedLookupClass, ALL_MODES); 634 635 if (requestedLookupClass == this.lookupClass) 636 return this; // keep same capabilities 637 int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); 638 if ((newModes & PACKAGE) != 0 639 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { 640 newModes &= ~(PACKAGE|PRIVATE); 641 } 642 // Allow nestmate lookups to be created without special privilege: 643 if ((newModes & PRIVATE) != 0 644 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { 645 newModes &= ~PRIVATE; 646 } 647 if ((newModes & PUBLIC) != 0 648 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { 649 // The requested class it not accessible from the lookup class. 650 // No permissions. 651 newModes = 0; 652 } 653 checkUnprivilegedlookupClass(requestedLookupClass, newModes); 654 return new Lookup(requestedLookupClass, newModes); 655 } 656 657 // Make sure outer class is initialized first. 658 // 659 // Android-changed: Removed unnecessary reference to IMPL_NAMES. 660 // static { IMPL_NAMES.getClass(); } 661 662 /** Version of lookup which is trusted minimally. 663 * It can only be used to create method handles to 664 * publicly accessible members. 665 */ 666 static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC); 667 668 /** Package-private version of lookup which is trusted. */ 669 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, ALL_MODES); 670 checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes)671 private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { 672 String name = lookupClass.getName(); 673 if (name.startsWith("java.lang.invoke.")) 674 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); 675 676 // For caller-sensitive MethodHandles.lookup() 677 // disallow lookup more restricted packages 678 // 679 // Android-changed: The bootstrap classloader isn't null. 680 if (allowedModes == ALL_MODES && 681 lookupClass.getClassLoader() == Object.class.getClassLoader()) { 682 if (name.startsWith("java.") || 683 (name.startsWith("sun.") 684 && !name.startsWith("sun.invoke.") 685 && !name.equals("sun.reflect.ReflectionFactory"))) { 686 throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); 687 } 688 } 689 } 690 691 /** 692 * Displays the name of the class from which lookups are to be made. 693 * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.) 694 * If there are restrictions on the access permitted to this lookup, 695 * this is indicated by adding a suffix to the class name, consisting 696 * of a slash and a keyword. The keyword represents the strongest 697 * allowed access, and is chosen as follows: 698 * <ul> 699 * <li>If no access is allowed, the suffix is "/noaccess". 700 * <li>If only public access is allowed, the suffix is "/public". 701 * <li>If only public and package access are allowed, the suffix is "/package". 702 * <li>If only public, package, and private access are allowed, the suffix is "/private". 703 * </ul> 704 * If none of the above cases apply, it is the case that full 705 * access (public, package, private, and protected) is allowed. 706 * In this case, no suffix is added. 707 * This is true only of an object obtained originally from 708 * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. 709 * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in} 710 * always have restricted access, and will display a suffix. 711 * <p> 712 * (It may seem strange that protected access should be 713 * stronger than private access. Viewed independently from 714 * package access, protected access is the first to be lost, 715 * because it requires a direct subclass relationship between 716 * caller and callee.) 717 * @see #in 718 */ 719 @Override toString()720 public String toString() { 721 String cname = lookupClass.getName(); 722 switch (allowedModes) { 723 case 0: // no privileges 724 return cname + "/noaccess"; 725 case PUBLIC: 726 return cname + "/public"; 727 case PUBLIC|PACKAGE: 728 return cname + "/package"; 729 case ALL_MODES & ~PROTECTED: 730 return cname + "/private"; 731 case ALL_MODES: 732 return cname; 733 // Android-changed: No support for TRUSTED callers. 734 // case TRUSTED: 735 // return "/trusted"; // internal only; not exported 736 default: // Should not happen, but it's a bitfield... 737 cname = cname + "/" + Integer.toHexString(allowedModes); 738 assert(false) : cname; 739 return cname; 740 } 741 } 742 743 /** 744 * Produces a method handle for a static method. 745 * The type of the method handle will be that of the method. 746 * (Since static methods do not take receivers, there is no 747 * additional receiver argument inserted into the method handle type, 748 * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.) 749 * The method and all its argument types must be accessible to the lookup object. 750 * <p> 751 * The returned method handle will have 752 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 753 * the method's variable arity modifier bit ({@code 0x0080}) is set. 754 * <p> 755 * If the returned method handle is invoked, the method's class will 756 * be initialized, if it has not already been initialized. 757 * <p><b>Example:</b> 758 * <blockquote><pre>{@code 759 import static java.lang.invoke.MethodHandles.*; 760 import static java.lang.invoke.MethodType.*; 761 ... 762 MethodHandle MH_asList = publicLookup().findStatic(Arrays.class, 763 "asList", methodType(List.class, Object[].class)); 764 assertEquals("[x, y]", MH_asList.invoke("x", "y").toString()); 765 * }</pre></blockquote> 766 * @param refc the class from which the method is accessed 767 * @param name the name of the method 768 * @param type the type of the method 769 * @return the desired method handle 770 * @throws NoSuchMethodException if the method does not exist 771 * @throws IllegalAccessException if access checking fails, 772 * or if the method is not {@code static}, 773 * or if the method's variable arity modifier bit 774 * is set and {@code asVarargsCollector} fails 775 * @exception SecurityException if a security manager is present and it 776 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 777 * @throws NullPointerException if any argument is null 778 */ 779 public findStatic(Class<?> refc, String name, MethodType type)780 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 781 Method method = refc.getDeclaredMethod(name, type.ptypes()); 782 final int modifiers = method.getModifiers(); 783 if (!Modifier.isStatic(modifiers)) { 784 throw new IllegalAccessException("Method" + method + " is not static"); 785 } 786 checkReturnType(method, type); 787 checkAccess(refc, method.getDeclaringClass(), modifiers, method.getName()); 788 return createMethodHandle(method, MethodHandle.INVOKE_STATIC, type); 789 } 790 findVirtualForMH(String name, MethodType type)791 private MethodHandle findVirtualForMH(String name, MethodType type) { 792 // these names require special lookups because of the implicit MethodType argument 793 if ("invoke".equals(name)) 794 return invoker(type); 795 if ("invokeExact".equals(name)) 796 return exactInvoker(type); 797 return null; 798 } 799 createMethodHandle(Method method, int handleKind, MethodType methodType)800 private static MethodHandle createMethodHandle(Method method, int handleKind, 801 MethodType methodType) { 802 MethodHandle mh = new MethodHandleImpl(method.getArtMethod(), handleKind, methodType); 803 if (method.isVarArgs()) { 804 return new Transformers.VarargsCollector(mh); 805 } else { 806 return mh; 807 } 808 } 809 810 /** 811 * Produces a method handle for a virtual method. 812 * The type of the method handle will be that of the method, 813 * with the receiver type (usually {@code refc}) prepended. 814 * The method and all its argument types must be accessible to the lookup object. 815 * <p> 816 * When called, the handle will treat the first argument as a receiver 817 * and dispatch on the receiver's type to determine which method 818 * implementation to enter. 819 * (The dispatching action is identical with that performed by an 820 * {@code invokevirtual} or {@code invokeinterface} instruction.) 821 * <p> 822 * The first argument will be of type {@code refc} if the lookup 823 * class has full privileges to access the member. Otherwise 824 * the member must be {@code protected} and the first argument 825 * will be restricted in type to the lookup class. 826 * <p> 827 * The returned method handle will have 828 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 829 * the method's variable arity modifier bit ({@code 0x0080}) is set. 830 * <p> 831 * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual} 832 * instructions and method handles produced by {@code findVirtual}, 833 * if the class is {@code MethodHandle} and the name string is 834 * {@code invokeExact} or {@code invoke}, the resulting 835 * method handle is equivalent to one produced by 836 * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or 837 * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker} 838 * with the same {@code type} argument. 839 * 840 * <b>Example:</b> 841 * <blockquote><pre>{@code 842 import static java.lang.invoke.MethodHandles.*; 843 import static java.lang.invoke.MethodType.*; 844 ... 845 MethodHandle MH_concat = publicLookup().findVirtual(String.class, 846 "concat", methodType(String.class, String.class)); 847 MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class, 848 "hashCode", methodType(int.class)); 849 MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class, 850 "hashCode", methodType(int.class)); 851 assertEquals("xy", (String) MH_concat.invokeExact("x", "y")); 852 assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy")); 853 assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy")); 854 // interface method: 855 MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class, 856 "subSequence", methodType(CharSequence.class, int.class, int.class)); 857 assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString()); 858 // constructor "internal method" must be accessed differently: 859 MethodType MT_newString = methodType(void.class); //()V for new String() 860 try { assertEquals("impossible", lookup() 861 .findVirtual(String.class, "<init>", MT_newString)); 862 } catch (NoSuchMethodException ex) { } // OK 863 MethodHandle MH_newString = publicLookup() 864 .findConstructor(String.class, MT_newString); 865 assertEquals("", (String) MH_newString.invokeExact()); 866 * }</pre></blockquote> 867 * 868 * @param refc the class or interface from which the method is accessed 869 * @param name the name of the method 870 * @param type the type of the method, with the receiver argument omitted 871 * @return the desired method handle 872 * @throws NoSuchMethodException if the method does not exist 873 * @throws IllegalAccessException if access checking fails, 874 * or if the method is {@code static} 875 * or if the method's variable arity modifier bit 876 * is set and {@code asVarargsCollector} fails 877 * @exception SecurityException if a security manager is present and it 878 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 879 * @throws NullPointerException if any argument is null 880 */ findVirtual(Class<?> refc, String name, MethodType type)881 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 882 // Special case : when we're looking up a virtual method on the MethodHandles class 883 // itself, we can return one of our specialized invokers. 884 if (refc == MethodHandle.class) { 885 MethodHandle mh = findVirtualForMH(name, type); 886 if (mh != null) { 887 return mh; 888 } 889 } 890 891 Method method = refc.getInstanceMethod(name, type.ptypes()); 892 if (method == null) { 893 // This is pretty ugly and a consequence of the MethodHandles API. We have to throw 894 // an IAE and not an NSME if the method exists but is static (even though the RI's 895 // IAE has a message that says "no such method"). We confine the ugliness and 896 // slowness to the failure case, and allow getInstanceMethod to remain fairly 897 // general. 898 try { 899 Method m = refc.getDeclaredMethod(name, type.ptypes()); 900 if (Modifier.isStatic(m.getModifiers())) { 901 throw new IllegalAccessException("Method" + m + " is static"); 902 } 903 } catch (NoSuchMethodException ignored) { 904 } 905 906 throw new NoSuchMethodException(name + " " + Arrays.toString(type.ptypes())); 907 } 908 checkReturnType(method, type); 909 910 // We have a valid method, perform access checks. 911 checkAccess(refc, method.getDeclaringClass(), method.getModifiers(), method.getName()); 912 913 // Insert the leading reference parameter. 914 MethodType handleType = type.insertParameterTypes(0, refc); 915 return createMethodHandle(method, MethodHandle.INVOKE_VIRTUAL, handleType); 916 } 917 918 /** 919 * Produces a method handle which creates an object and initializes it, using 920 * the constructor of the specified type. 921 * The parameter types of the method handle will be those of the constructor, 922 * while the return type will be a reference to the constructor's class. 923 * The constructor and all its argument types must be accessible to the lookup object. 924 * <p> 925 * The requested type must have a return type of {@code void}. 926 * (This is consistent with the JVM's treatment of constructor type descriptors.) 927 * <p> 928 * The returned method handle will have 929 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 930 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 931 * <p> 932 * If the returned method handle is invoked, the constructor's class will 933 * be initialized, if it has not already been initialized. 934 * <p><b>Example:</b> 935 * <blockquote><pre>{@code 936 import static java.lang.invoke.MethodHandles.*; 937 import static java.lang.invoke.MethodType.*; 938 ... 939 MethodHandle MH_newArrayList = publicLookup().findConstructor( 940 ArrayList.class, methodType(void.class, Collection.class)); 941 Collection orig = Arrays.asList("x", "y"); 942 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig); 943 assert(orig != copy); 944 assertEquals(orig, copy); 945 // a variable-arity constructor: 946 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor( 947 ProcessBuilder.class, methodType(void.class, String[].class)); 948 ProcessBuilder pb = (ProcessBuilder) 949 MH_newProcessBuilder.invoke("x", "y", "z"); 950 assertEquals("[x, y, z]", pb.command().toString()); 951 * }</pre></blockquote> 952 * @param refc the class or interface from which the method is accessed 953 * @param type the type of the method, with the receiver argument omitted, and a void return type 954 * @return the desired method handle 955 * @throws NoSuchMethodException if the constructor does not exist 956 * @throws IllegalAccessException if access checking fails 957 * or if the method's variable arity modifier bit 958 * is set and {@code asVarargsCollector} fails 959 * @exception SecurityException if a security manager is present and it 960 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 961 * @throws NullPointerException if any argument is null 962 */ findConstructor(Class<?> refc, MethodType type)963 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { 964 if (refc.isArray()) { 965 throw new NoSuchMethodException("no constructor for array class: " + refc.getName()); 966 } 967 // The queried |type| is (PT1,PT2,..)V 968 Constructor constructor = refc.getDeclaredConstructor(type.ptypes()); 969 if (constructor == null) { 970 throw new NoSuchMethodException( 971 "No constructor for " + constructor.getDeclaringClass() + " matching " + type); 972 } 973 checkAccess(refc, constructor.getDeclaringClass(), constructor.getModifiers(), 974 constructor.getName()); 975 976 return createMethodHandleForConstructor(constructor); 977 } 978 createMethodHandleForConstructor(Constructor constructor)979 private MethodHandle createMethodHandleForConstructor(Constructor constructor) { 980 Class<?> refc = constructor.getDeclaringClass(); 981 MethodType constructorType = 982 MethodType.methodType(refc, constructor.getParameterTypes()); 983 MethodHandle mh; 984 if (refc == String.class) { 985 // String constructors have optimized StringFactory methods 986 // that matches returned type. These factory methods combine the 987 // memory allocation and initialization calls for String objects. 988 mh = new MethodHandleImpl(constructor.getArtMethod(), MethodHandle.INVOKE_DIRECT, 989 constructorType); 990 } else { 991 // Constructors for all other classes use a Construct transformer to perform 992 // their memory allocation and call to <init>. 993 MethodType initType = initMethodType(constructorType); 994 MethodHandle initHandle = new MethodHandleImpl( 995 constructor.getArtMethod(), MethodHandle.INVOKE_DIRECT, initType); 996 mh = new Transformers.Construct(initHandle, constructorType); 997 } 998 999 if (constructor.isVarArgs()) { 1000 mh = new Transformers.VarargsCollector(mh); 1001 } 1002 return mh; 1003 } 1004 initMethodType(MethodType constructorType)1005 private static MethodType initMethodType(MethodType constructorType) { 1006 // Returns a MethodType appropriate for class <init> 1007 // methods. Constructor MethodTypes have the form 1008 // (PT1,PT2,...)C and class <init> MethodTypes have the 1009 // form (C,PT1,PT2,...)V. 1010 assert constructorType.rtype() != void.class; 1011 1012 // Insert constructorType C as the first parameter type in 1013 // the MethodType for <init>. 1014 Class<?> [] initPtypes = new Class<?> [constructorType.ptypes().length + 1]; 1015 initPtypes[0] = constructorType.rtype(); 1016 System.arraycopy(constructorType.ptypes(), 0, initPtypes, 1, 1017 constructorType.ptypes().length); 1018 1019 // Set the return type for the <init> MethodType to be void. 1020 return MethodType.methodType(void.class, initPtypes); 1021 } 1022 1023 /** 1024 * Produces an early-bound method handle for a virtual method. 1025 * It will bypass checks for overriding methods on the receiver, 1026 * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial} 1027 * instruction from within the explicitly specified {@code specialCaller}. 1028 * The type of the method handle will be that of the method, 1029 * with a suitably restricted receiver type prepended. 1030 * (The receiver type will be {@code specialCaller} or a subtype.) 1031 * The method and all its argument types must be accessible 1032 * to the lookup object. 1033 * <p> 1034 * Before method resolution, 1035 * if the explicitly specified caller class is not identical with the 1036 * lookup class, or if this lookup object does not have 1037 * <a href="MethodHandles.Lookup.html#privacc">private access</a> 1038 * privileges, the access fails. 1039 * <p> 1040 * The returned method handle will have 1041 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1042 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1043 * <p style="font-size:smaller;"> 1044 * <em>(Note: JVM internal methods named {@code "<init>"} are not visible to this API, 1045 * even though the {@code invokespecial} instruction can refer to them 1046 * in special circumstances. Use {@link #findConstructor findConstructor} 1047 * to access instance initialization methods in a safe manner.)</em> 1048 * <p><b>Example:</b> 1049 * <blockquote><pre>{@code 1050 import static java.lang.invoke.MethodHandles.*; 1051 import static java.lang.invoke.MethodType.*; 1052 ... 1053 static class Listie extends ArrayList { 1054 public String toString() { return "[wee Listie]"; } 1055 static Lookup lookup() { return MethodHandles.lookup(); } 1056 } 1057 ... 1058 // no access to constructor via invokeSpecial: 1059 MethodHandle MH_newListie = Listie.lookup() 1060 .findConstructor(Listie.class, methodType(void.class)); 1061 Listie l = (Listie) MH_newListie.invokeExact(); 1062 try { assertEquals("impossible", Listie.lookup().findSpecial( 1063 Listie.class, "<init>", methodType(void.class), Listie.class)); 1064 } catch (NoSuchMethodException ex) { } // OK 1065 // access to super and self methods via invokeSpecial: 1066 MethodHandle MH_super = Listie.lookup().findSpecial( 1067 ArrayList.class, "toString" , methodType(String.class), Listie.class); 1068 MethodHandle MH_this = Listie.lookup().findSpecial( 1069 Listie.class, "toString" , methodType(String.class), Listie.class); 1070 MethodHandle MH_duper = Listie.lookup().findSpecial( 1071 Object.class, "toString" , methodType(String.class), Listie.class); 1072 assertEquals("[]", (String) MH_super.invokeExact(l)); 1073 assertEquals(""+l, (String) MH_this.invokeExact(l)); 1074 assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method 1075 try { assertEquals("inaccessible", Listie.lookup().findSpecial( 1076 String.class, "toString", methodType(String.class), Listie.class)); 1077 } catch (IllegalAccessException ex) { } // OK 1078 Listie subl = new Listie() { public String toString() { return "[subclass]"; } }; 1079 assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method 1080 * }</pre></blockquote> 1081 * 1082 * @param refc the class or interface from which the method is accessed 1083 * @param name the name of the method (which must not be "<init>") 1084 * @param type the type of the method, with the receiver argument omitted 1085 * @param specialCaller the proposed calling class to perform the {@code invokespecial} 1086 * @return the desired method handle 1087 * @throws NoSuchMethodException if the method does not exist 1088 * @throws IllegalAccessException if access checking fails 1089 * or if the method's variable arity modifier bit 1090 * is set and {@code asVarargsCollector} fails 1091 * @exception SecurityException if a security manager is present and it 1092 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1093 * @throws NullPointerException if any argument is null 1094 */ findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller)1095 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, 1096 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { 1097 if (specialCaller == null) { 1098 throw new NullPointerException("specialCaller == null"); 1099 } 1100 1101 if (type == null) { 1102 throw new NullPointerException("type == null"); 1103 } 1104 1105 if (name == null) { 1106 throw new NullPointerException("name == null"); 1107 } 1108 1109 if (refc == null) { 1110 throw new NullPointerException("ref == null"); 1111 } 1112 1113 // Make sure that the special caller is identical to the lookup class or that we have 1114 // private access. 1115 checkSpecialCaller(specialCaller); 1116 1117 // Even though constructors are invoked using a "special" invoke, handles to them can't 1118 // be created using findSpecial. Callers must use findConstructor instead. Similarly, 1119 // there is no path for calling static class initializers. 1120 if (name.startsWith("<")) { 1121 throw new NoSuchMethodException(name + " is not a valid method name."); 1122 } 1123 1124 Method method = refc.getDeclaredMethod(name, type.ptypes()); 1125 checkReturnType(method, type); 1126 return findSpecial(method, type, refc, specialCaller); 1127 } 1128 findSpecial(Method method, MethodType type, Class<?> refc, Class<?> specialCaller)1129 private MethodHandle findSpecial(Method method, MethodType type, 1130 Class<?> refc, Class<?> specialCaller) 1131 throws IllegalAccessException { 1132 if (Modifier.isStatic(method.getModifiers())) { 1133 throw new IllegalAccessException("expected a non-static method:" + method); 1134 } 1135 1136 if (Modifier.isPrivate(method.getModifiers())) { 1137 // Since this is a private method, we'll need to also make sure that the 1138 // lookup class is the same as the refering class. We've already checked that 1139 // the specialCaller is the same as the special lookup class, both of these must 1140 // be the same as the declaring class(*) in order to access the private method. 1141 // 1142 // (*) Well, this isn't true for nested classes but OpenJDK doesn't support those 1143 // either. 1144 if (refc != lookupClass()) { 1145 throw new IllegalAccessException("no private access for invokespecial : " 1146 + refc + ", from" + this); 1147 } 1148 1149 // This is a private method, so there's nothing special to do. 1150 MethodType handleType = type.insertParameterTypes(0, refc); 1151 return createMethodHandle(method, MethodHandle.INVOKE_DIRECT, handleType); 1152 } 1153 1154 // This is a public, protected or package-private method, which means we're expecting 1155 // invoke-super semantics. We'll have to restrict the receiver type appropriately on the 1156 // handle once we check that there really is a "super" relationship between them. 1157 if (!method.getDeclaringClass().isAssignableFrom(specialCaller)) { 1158 throw new IllegalAccessException(refc + "is not assignable from " + specialCaller); 1159 } 1160 1161 // Note that we restrict the receiver to "specialCaller" instances. 1162 MethodType handleType = type.insertParameterTypes(0, specialCaller); 1163 return createMethodHandle(method, MethodHandle.INVOKE_SUPER, handleType); 1164 } 1165 1166 /** 1167 * Produces a method handle giving read access to a non-static field. 1168 * The type of the method handle will have a return type of the field's 1169 * value type. 1170 * The method handle's single argument will be the instance containing 1171 * the field. 1172 * Access checking is performed immediately on behalf of the lookup class. 1173 * @param refc the class or interface from which the method is accessed 1174 * @param name the field's name 1175 * @param type the field's type 1176 * @return a method handle which can load values from the field 1177 * @throws NoSuchFieldException if the field does not exist 1178 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} 1179 * @exception SecurityException if a security manager is present and it 1180 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1181 * @throws NullPointerException if any argument is null 1182 */ findGetter(Class<?> refc, String name, Class<?> type)1183 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 1184 return findAccessor(refc, name, type, MethodHandle.IGET); 1185 } 1186 findAccessor(Class<?> refc, String name, Class<?> type, int kind)1187 private MethodHandle findAccessor(Class<?> refc, String name, Class<?> type, int kind) 1188 throws NoSuchFieldException, IllegalAccessException { 1189 final Field field = refc.getDeclaredField(name); 1190 final Class<?> fieldType = field.getType(); 1191 if (fieldType != type) { 1192 throw new NoSuchFieldException( 1193 "Field has wrong type: " + fieldType + " != " + type); 1194 } 1195 1196 return findAccessor(field, refc, type, kind, true /* performAccessChecks */); 1197 } 1198 findAccessor(Field field, Class<?> refc, Class<?> fieldType, int kind, boolean performAccessChecks)1199 private MethodHandle findAccessor(Field field, Class<?> refc, Class<?> fieldType, int kind, 1200 boolean performAccessChecks) 1201 throws IllegalAccessException { 1202 if (!performAccessChecks) { 1203 checkAccess(refc, field.getDeclaringClass(), field.getModifiers(), field.getName()); 1204 } 1205 1206 final boolean isStaticKind = kind == MethodHandle.SGET || kind == MethodHandle.SPUT; 1207 final int modifiers = field.getModifiers(); 1208 if (Modifier.isStatic(modifiers) != isStaticKind) { 1209 String reason = "Field " + field + " is " + 1210 (isStaticKind ? "not " : "") + "static"; 1211 throw new IllegalAccessException(reason); 1212 } 1213 1214 final boolean isSetterKind = kind == MethodHandle.IPUT || kind == MethodHandle.SPUT; 1215 if (Modifier.isFinal(modifiers) && isSetterKind) { 1216 throw new IllegalAccessException("Field " + field + " is final"); 1217 } 1218 1219 final MethodType methodType; 1220 switch (kind) { 1221 case MethodHandle.SGET: 1222 methodType = MethodType.methodType(fieldType); 1223 break; 1224 case MethodHandle.SPUT: 1225 methodType = MethodType.methodType(void.class, fieldType); 1226 break; 1227 case MethodHandle.IGET: 1228 methodType = MethodType.methodType(fieldType, refc); 1229 break; 1230 case MethodHandle.IPUT: 1231 methodType = MethodType.methodType(void.class, refc, fieldType); 1232 break; 1233 default: 1234 throw new IllegalArgumentException("Invalid kind " + kind); 1235 } 1236 return new MethodHandleImpl(field.getArtField(), kind, methodType); 1237 } 1238 1239 /** 1240 * Produces a method handle giving write access to a non-static field. 1241 * The type of the method handle will have a void return type. 1242 * The method handle will take two arguments, the instance containing 1243 * the field, and the value to be stored. 1244 * The second argument will be of the field's value type. 1245 * Access checking is performed immediately on behalf of the lookup class. 1246 * @param refc the class or interface from which the method is accessed 1247 * @param name the field's name 1248 * @param type the field's type 1249 * @return a method handle which can store values into the field 1250 * @throws NoSuchFieldException if the field does not exist 1251 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} 1252 * @exception SecurityException if a security manager is present and it 1253 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1254 * @throws NullPointerException if any argument is null 1255 */ findSetter(Class<?> refc, String name, Class<?> type)1256 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 1257 return findAccessor(refc, name, type, MethodHandle.IPUT); 1258 } 1259 1260 /** 1261 * Produces a method handle giving read access to a static field. 1262 * The type of the method handle will have a return type of the field's 1263 * value type. 1264 * The method handle will take no arguments. 1265 * Access checking is performed immediately on behalf of the lookup class. 1266 * <p> 1267 * If the returned method handle is invoked, the field's class will 1268 * be initialized, if it has not already been initialized. 1269 * @param refc the class or interface from which the method is accessed 1270 * @param name the field's name 1271 * @param type the field's type 1272 * @return a method handle which can load values from the field 1273 * @throws NoSuchFieldException if the field does not exist 1274 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} 1275 * @exception SecurityException if a security manager is present and it 1276 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1277 * @throws NullPointerException if any argument is null 1278 */ findStaticGetter(Class<?> refc, String name, Class<?> type)1279 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 1280 return findAccessor(refc, name, type, MethodHandle.SGET); 1281 } 1282 1283 /** 1284 * Produces a method handle giving write access to a static field. 1285 * The type of the method handle will have a void return type. 1286 * The method handle will take a single 1287 * argument, of the field's value type, the value to be stored. 1288 * Access checking is performed immediately on behalf of the lookup class. 1289 * <p> 1290 * If the returned method handle is invoked, the field's class will 1291 * be initialized, if it has not already been initialized. 1292 * @param refc the class or interface from which the method is accessed 1293 * @param name the field's name 1294 * @param type the field's type 1295 * @return a method handle which can store values into the field 1296 * @throws NoSuchFieldException if the field does not exist 1297 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} 1298 * @exception SecurityException if a security manager is present and it 1299 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1300 * @throws NullPointerException if any argument is null 1301 */ findStaticSetter(Class<?> refc, String name, Class<?> type)1302 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { 1303 return findAccessor(refc, name, type, MethodHandle.SPUT); 1304 } 1305 1306 /** 1307 * Produces an early-bound method handle for a non-static method. 1308 * The receiver must have a supertype {@code defc} in which a method 1309 * of the given name and type is accessible to the lookup class. 1310 * The method and all its argument types must be accessible to the lookup object. 1311 * The type of the method handle will be that of the method, 1312 * without any insertion of an additional receiver parameter. 1313 * The given receiver will be bound into the method handle, 1314 * so that every call to the method handle will invoke the 1315 * requested method on the given receiver. 1316 * <p> 1317 * The returned method handle will have 1318 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1319 * the method's variable arity modifier bit ({@code 0x0080}) is set 1320 * <em>and</em> the trailing array argument is not the only argument. 1321 * (If the trailing array argument is the only argument, 1322 * the given receiver value will be bound to it.) 1323 * <p> 1324 * This is equivalent to the following code: 1325 * <blockquote><pre>{@code 1326 import static java.lang.invoke.MethodHandles.*; 1327 import static java.lang.invoke.MethodType.*; 1328 ... 1329 MethodHandle mh0 = lookup().findVirtual(defc, name, type); 1330 MethodHandle mh1 = mh0.bindTo(receiver); 1331 MethodType mt1 = mh1.type(); 1332 if (mh0.isVarargsCollector()) 1333 mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); 1334 return mh1; 1335 * }</pre></blockquote> 1336 * where {@code defc} is either {@code receiver.getClass()} or a super 1337 * type of that class, in which the requested method is accessible 1338 * to the lookup class. 1339 * (Note that {@code bindTo} does not preserve variable arity.) 1340 * @param receiver the object from which the method is accessed 1341 * @param name the name of the method 1342 * @param type the type of the method, with the receiver argument omitted 1343 * @return the desired method handle 1344 * @throws NoSuchMethodException if the method does not exist 1345 * @throws IllegalAccessException if access checking fails 1346 * or if the method's variable arity modifier bit 1347 * is set and {@code asVarargsCollector} fails 1348 * @exception SecurityException if a security manager is present and it 1349 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1350 * @throws NullPointerException if any argument is null 1351 * @see MethodHandle#bindTo 1352 * @see #findVirtual 1353 */ bind(Object receiver, String name, MethodType type)1354 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { 1355 MethodHandle handle = findVirtual(receiver.getClass(), name, type); 1356 MethodHandle adapter = handle.bindTo(receiver); 1357 MethodType adapterType = adapter.type(); 1358 if (handle.isVarargsCollector()) { 1359 adapter = adapter.asVarargsCollector( 1360 adapterType.parameterType(adapterType.parameterCount() - 1)); 1361 } 1362 1363 return adapter; 1364 } 1365 1366 /** 1367 * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a> 1368 * to <i>m</i>, if the lookup class has permission. 1369 * If <i>m</i> is non-static, the receiver argument is treated as an initial argument. 1370 * If <i>m</i> is virtual, overriding is respected on every call. 1371 * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped. 1372 * The type of the method handle will be that of the method, 1373 * with the receiver type prepended (but only if it is non-static). 1374 * If the method's {@code accessible} flag is not set, 1375 * access checking is performed immediately on behalf of the lookup class. 1376 * If <i>m</i> is not public, do not share the resulting handle with untrusted parties. 1377 * <p> 1378 * The returned method handle will have 1379 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1380 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1381 * <p> 1382 * If <i>m</i> is static, and 1383 * if the returned method handle is invoked, the method's class will 1384 * be initialized, if it has not already been initialized. 1385 * @param m the reflected method 1386 * @return a method handle which can invoke the reflected method 1387 * @throws IllegalAccessException if access checking fails 1388 * or if the method's variable arity modifier bit 1389 * is set and {@code asVarargsCollector} fails 1390 * @throws NullPointerException if the argument is null 1391 */ unreflect(Method m)1392 public MethodHandle unreflect(Method m) throws IllegalAccessException { 1393 if (m == null) { 1394 throw new NullPointerException("m == null"); 1395 } 1396 1397 MethodType methodType = MethodType.methodType(m.getReturnType(), 1398 m.getParameterTypes()); 1399 1400 // We should only perform access checks if setAccessible hasn't been called yet. 1401 if (!m.isAccessible()) { 1402 checkAccess(m.getDeclaringClass(), m.getDeclaringClass(), m.getModifiers(), 1403 m.getName()); 1404 } 1405 1406 if (Modifier.isStatic(m.getModifiers())) { 1407 return createMethodHandle(m, MethodHandle.INVOKE_STATIC, methodType); 1408 } else { 1409 methodType = methodType.insertParameterTypes(0, m.getDeclaringClass()); 1410 return createMethodHandle(m, MethodHandle.INVOKE_VIRTUAL, methodType); 1411 } 1412 } 1413 1414 /** 1415 * Produces a method handle for a reflected method. 1416 * It will bypass checks for overriding methods on the receiver, 1417 * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial} 1418 * instruction from within the explicitly specified {@code specialCaller}. 1419 * The type of the method handle will be that of the method, 1420 * with a suitably restricted receiver type prepended. 1421 * (The receiver type will be {@code specialCaller} or a subtype.) 1422 * If the method's {@code accessible} flag is not set, 1423 * access checking is performed immediately on behalf of the lookup class, 1424 * as if {@code invokespecial} instruction were being linked. 1425 * <p> 1426 * Before method resolution, 1427 * if the explicitly specified caller class is not identical with the 1428 * lookup class, or if this lookup object does not have 1429 * <a href="MethodHandles.Lookup.html#privacc">private access</a> 1430 * privileges, the access fails. 1431 * <p> 1432 * The returned method handle will have 1433 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1434 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1435 * @param m the reflected method 1436 * @param specialCaller the class nominally calling the method 1437 * @return a method handle which can invoke the reflected method 1438 * @throws IllegalAccessException if access checking fails 1439 * or if the method's variable arity modifier bit 1440 * is set and {@code asVarargsCollector} fails 1441 * @throws NullPointerException if any argument is null 1442 */ unreflectSpecial(Method m, Class<?> specialCaller)1443 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { 1444 if (m == null) { 1445 throw new NullPointerException("m == null"); 1446 } 1447 1448 if (specialCaller == null) { 1449 throw new NullPointerException("specialCaller == null"); 1450 } 1451 1452 if (!m.isAccessible()) { 1453 checkSpecialCaller(specialCaller); 1454 } 1455 1456 final MethodType methodType = MethodType.methodType(m.getReturnType(), 1457 m.getParameterTypes()); 1458 return findSpecial(m, methodType, m.getDeclaringClass() /* refc */, specialCaller); 1459 } 1460 1461 /** 1462 * Produces a method handle for a reflected constructor. 1463 * The type of the method handle will be that of the constructor, 1464 * with the return type changed to the declaring class. 1465 * The method handle will perform a {@code newInstance} operation, 1466 * creating a new instance of the constructor's class on the 1467 * arguments passed to the method handle. 1468 * <p> 1469 * If the constructor's {@code accessible} flag is not set, 1470 * access checking is performed immediately on behalf of the lookup class. 1471 * <p> 1472 * The returned method handle will have 1473 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1474 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 1475 * <p> 1476 * If the returned method handle is invoked, the constructor's class will 1477 * be initialized, if it has not already been initialized. 1478 * @param c the reflected constructor 1479 * @return a method handle which can invoke the reflected constructor 1480 * @throws IllegalAccessException if access checking fails 1481 * or if the method's variable arity modifier bit 1482 * is set and {@code asVarargsCollector} fails 1483 * @throws NullPointerException if the argument is null 1484 */ unreflectConstructor(Constructor<?> c)1485 public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { 1486 if (c == null) { 1487 throw new NullPointerException("c == null"); 1488 } 1489 1490 if (!c.isAccessible()) { 1491 checkAccess(c.getDeclaringClass(), c.getDeclaringClass(), c.getModifiers(), 1492 c.getName()); 1493 } 1494 1495 return createMethodHandleForConstructor(c); 1496 } 1497 1498 /** 1499 * Produces a method handle giving read access to a reflected field. 1500 * The type of the method handle will have a return type of the field's 1501 * value type. 1502 * If the field is static, the method handle will take no arguments. 1503 * Otherwise, its single argument will be the instance containing 1504 * the field. 1505 * If the field's {@code accessible} flag is not set, 1506 * access checking is performed immediately on behalf of the lookup class. 1507 * <p> 1508 * If the field is static, and 1509 * if the returned method handle is invoked, the field's class will 1510 * be initialized, if it has not already been initialized. 1511 * @param f the reflected field 1512 * @return a method handle which can load values from the reflected field 1513 * @throws IllegalAccessException if access checking fails 1514 * @throws NullPointerException if the argument is null 1515 */ unreflectGetter(Field f)1516 public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { 1517 return findAccessor(f, f.getDeclaringClass(), f.getType(), 1518 Modifier.isStatic(f.getModifiers()) ? MethodHandle.SGET : MethodHandle.IGET, 1519 f.isAccessible() /* performAccessChecks */); 1520 } 1521 1522 /** 1523 * Produces a method handle giving write access to a reflected field. 1524 * The type of the method handle will have a void return type. 1525 * If the field is static, the method handle will take a single 1526 * argument, of the field's value type, the value to be stored. 1527 * Otherwise, the two arguments will be the instance containing 1528 * the field, and the value to be stored. 1529 * If the field's {@code accessible} flag is not set, 1530 * access checking is performed immediately on behalf of the lookup class. 1531 * <p> 1532 * If the field is static, and 1533 * if the returned method handle is invoked, the field's class will 1534 * be initialized, if it has not already been initialized. 1535 * @param f the reflected field 1536 * @return a method handle which can store values into the reflected field 1537 * @throws IllegalAccessException if access checking fails 1538 * @throws NullPointerException if the argument is null 1539 */ unreflectSetter(Field f)1540 public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { 1541 return findAccessor(f, f.getDeclaringClass(), f.getType(), 1542 Modifier.isStatic(f.getModifiers()) ? MethodHandle.SPUT : MethodHandle.IPUT, 1543 f.isAccessible() /* performAccessChecks */); 1544 } 1545 1546 /** 1547 * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a> 1548 * created by this lookup object or a similar one. 1549 * Security and access checks are performed to ensure that this lookup object 1550 * is capable of reproducing the target method handle. 1551 * This means that the cracking may fail if target is a direct method handle 1552 * but was created by an unrelated lookup object. 1553 * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> 1554 * and was created by a lookup object for a different class. 1555 * @param target a direct method handle to crack into symbolic reference components 1556 * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object 1557 * @exception SecurityException if a security manager is present and it 1558 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> 1559 * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails 1560 * @exception NullPointerException if the target is {@code null} 1561 * @see MethodHandleInfo 1562 * @since 1.8 1563 */ revealDirect(MethodHandle target)1564 public MethodHandleInfo revealDirect(MethodHandle target) { 1565 MethodHandleImpl directTarget = getMethodHandleImpl(target); 1566 MethodHandleInfo info = directTarget.reveal(); 1567 1568 try { 1569 checkAccess(lookupClass(), info.getDeclaringClass(), info.getModifiers(), 1570 info.getName()); 1571 } catch (IllegalAccessException exception) { 1572 throw new IllegalArgumentException("Unable to access memeber.", exception); 1573 } 1574 1575 return info; 1576 } 1577 hasPrivateAccess()1578 private boolean hasPrivateAccess() { 1579 return (allowedModes & PRIVATE) != 0; 1580 } 1581 1582 /** Check public/protected/private bits on the symbolic reference class and its member. */ checkAccess(Class<?> refc, Class<?> defc, int mods, String methName)1583 void checkAccess(Class<?> refc, Class<?> defc, int mods, String methName) 1584 throws IllegalAccessException { 1585 int allowedModes = this.allowedModes; 1586 1587 if (Modifier.isProtected(mods) && 1588 defc == Object.class && 1589 "clone".equals(methName) && 1590 refc.isArray()) { 1591 // The JVM does this hack also. 1592 // (See ClassVerifier::verify_invoke_instructions 1593 // and LinkResolver::check_method_accessability.) 1594 // Because the JVM does not allow separate methods on array types, 1595 // there is no separate method for int[].clone. 1596 // All arrays simply inherit Object.clone. 1597 // But for access checking logic, we make Object.clone 1598 // (normally protected) appear to be public. 1599 // Later on, when the DirectMethodHandle is created, 1600 // its leading argument will be restricted to the 1601 // requested array type. 1602 // N.B. The return type is not adjusted, because 1603 // that is *not* the bytecode behavior. 1604 mods ^= Modifier.PROTECTED | Modifier.PUBLIC; 1605 } 1606 1607 if (Modifier.isProtected(mods) && Modifier.isConstructor(mods)) { 1608 // cannot "new" a protected ctor in a different package 1609 mods ^= Modifier.PROTECTED; 1610 } 1611 1612 if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0) 1613 return; // common case 1614 int requestedModes = fixmods(mods); // adjust 0 => PACKAGE 1615 if ((requestedModes & allowedModes) != 0) { 1616 if (VerifyAccess.isMemberAccessible(refc, defc, mods, lookupClass(), allowedModes)) 1617 return; 1618 } else { 1619 // Protected members can also be checked as if they were package-private. 1620 if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0 1621 && VerifyAccess.isSamePackage(defc, lookupClass())) 1622 return; 1623 } 1624 1625 throwMakeAccessException(accessFailedMessage(refc, defc, mods), this); 1626 } 1627 accessFailedMessage(Class<?> refc, Class<?> defc, int mods)1628 String accessFailedMessage(Class<?> refc, Class<?> defc, int mods) { 1629 // check the class first: 1630 boolean classOK = (Modifier.isPublic(defc.getModifiers()) && 1631 (defc == refc || 1632 Modifier.isPublic(refc.getModifiers()))); 1633 if (!classOK && (allowedModes & PACKAGE) != 0) { 1634 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) && 1635 (defc == refc || 1636 VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); 1637 } 1638 if (!classOK) 1639 return "class is not public"; 1640 if (Modifier.isPublic(mods)) 1641 return "access to public member failed"; // (how?) 1642 if (Modifier.isPrivate(mods)) 1643 return "member is private"; 1644 if (Modifier.isProtected(mods)) 1645 return "member is protected"; 1646 return "member is private to package"; 1647 } 1648 1649 // Android-changed: checkSpecialCaller assumes that ALLOW_NESTMATE_ACCESS = false, 1650 // as in upstream OpenJDK. 1651 // 1652 // private static final boolean ALLOW_NESTMATE_ACCESS = false; 1653 checkSpecialCaller(Class<?> specialCaller)1654 private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { 1655 // Android-changed: No support for TRUSTED lookups. Also construct the 1656 // IllegalAccessException by hand because the upstream code implicitly assumes 1657 // that the lookupClass == specialCaller. 1658 // 1659 // if (allowedModes == TRUSTED) return; 1660 if (!hasPrivateAccess() || (specialCaller != lookupClass())) { 1661 throw new IllegalAccessException("no private access for invokespecial : " 1662 + specialCaller + ", from" + this); 1663 } 1664 } 1665 throwMakeAccessException(String message, Object from)1666 private void throwMakeAccessException(String message, Object from) throws 1667 IllegalAccessException{ 1668 message = message + ": "+ toString(); 1669 if (from != null) message += ", from " + from; 1670 throw new IllegalAccessException(message); 1671 } 1672 checkReturnType(Method method, MethodType methodType)1673 private void checkReturnType(Method method, MethodType methodType) 1674 throws NoSuchMethodException { 1675 if (method.getReturnType() != methodType.rtype()) { 1676 throw new NoSuchMethodException(method.getName() + methodType); 1677 } 1678 } 1679 } 1680 1681 /** 1682 * "Cracks" {@code target} to reveal the underlying {@code MethodHandleImpl}. 1683 */ getMethodHandleImpl(MethodHandle target)1684 private static MethodHandleImpl getMethodHandleImpl(MethodHandle target) { 1685 // Special case : We implement handles to constructors as transformers, 1686 // so we must extract the underlying handle from the transformer. 1687 if (target instanceof Transformers.Construct) { 1688 target = ((Transformers.Construct) target).getConstructorHandle(); 1689 } 1690 1691 // Special case: Var-args methods are also implemented as Transformers, 1692 // so we should get the underlying handle in that case as well. 1693 if (target instanceof Transformers.VarargsCollector) { 1694 target = target.asFixedArity(); 1695 } 1696 1697 if (target instanceof MethodHandleImpl) { 1698 return (MethodHandleImpl) target; 1699 } 1700 1701 throw new IllegalArgumentException(target + " is not a direct handle"); 1702 } 1703 1704 /** 1705 * Produces a method handle giving read access to elements of an array. 1706 * The type of the method handle will have a return type of the array's 1707 * element type. Its first argument will be the array type, 1708 * and the second will be {@code int}. 1709 * @param arrayClass an array type 1710 * @return a method handle which can load values from the given array type 1711 * @throws NullPointerException if the argument is null 1712 * @throws IllegalArgumentException if arrayClass is not an array type 1713 */ 1714 public static arrayElementGetter(Class<?> arrayClass)1715 MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException { 1716 final Class<?> componentType = arrayClass.getComponentType(); 1717 if (componentType == null) { 1718 throw new IllegalArgumentException("Not an array type: " + arrayClass); 1719 } 1720 1721 if (componentType.isPrimitive()) { 1722 try { 1723 return Lookup.PUBLIC_LOOKUP.findStatic(MethodHandles.class, 1724 "arrayElementGetter", 1725 MethodType.methodType(componentType, arrayClass, int.class)); 1726 } catch (NoSuchMethodException | IllegalAccessException exception) { 1727 throw new AssertionError(exception); 1728 } 1729 } 1730 1731 return new Transformers.ReferenceArrayElementGetter(arrayClass); 1732 } 1733 arrayElementGetter(byte[] array, int i)1734 /** @hide */ public static byte arrayElementGetter(byte[] array, int i) { return array[i]; } arrayElementGetter(boolean[] array, int i)1735 /** @hide */ public static boolean arrayElementGetter(boolean[] array, int i) { return array[i]; } arrayElementGetter(char[] array, int i)1736 /** @hide */ public static char arrayElementGetter(char[] array, int i) { return array[i]; } arrayElementGetter(short[] array, int i)1737 /** @hide */ public static short arrayElementGetter(short[] array, int i) { return array[i]; } arrayElementGetter(int[] array, int i)1738 /** @hide */ public static int arrayElementGetter(int[] array, int i) { return array[i]; } arrayElementGetter(long[] array, int i)1739 /** @hide */ public static long arrayElementGetter(long[] array, int i) { return array[i]; } arrayElementGetter(float[] array, int i)1740 /** @hide */ public static float arrayElementGetter(float[] array, int i) { return array[i]; } arrayElementGetter(double[] array, int i)1741 /** @hide */ public static double arrayElementGetter(double[] array, int i) { return array[i]; } 1742 1743 /** 1744 * Produces a method handle giving write access to elements of an array. 1745 * The type of the method handle will have a void return type. 1746 * Its last argument will be the array's element type. 1747 * The first and second arguments will be the array type and int. 1748 * @param arrayClass the class of an array 1749 * @return a method handle which can store values into the array type 1750 * @throws NullPointerException if the argument is null 1751 * @throws IllegalArgumentException if arrayClass is not an array type 1752 */ 1753 public static arrayElementSetter(Class<?> arrayClass)1754 MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException { 1755 final Class<?> componentType = arrayClass.getComponentType(); 1756 if (componentType == null) { 1757 throw new IllegalArgumentException("Not an array type: " + arrayClass); 1758 } 1759 1760 if (componentType.isPrimitive()) { 1761 try { 1762 return Lookup.PUBLIC_LOOKUP.findStatic(MethodHandles.class, 1763 "arrayElementSetter", 1764 MethodType.methodType(void.class, arrayClass, int.class, componentType)); 1765 } catch (NoSuchMethodException | IllegalAccessException exception) { 1766 throw new AssertionError(exception); 1767 } 1768 } 1769 1770 return new Transformers.ReferenceArrayElementSetter(arrayClass); 1771 } 1772 1773 /** @hide */ arrayElementSetter(byte[] array, int i, byte val)1774 public static void arrayElementSetter(byte[] array, int i, byte val) { array[i] = val; } 1775 /** @hide */ arrayElementSetter(boolean[] array, int i, boolean val)1776 public static void arrayElementSetter(boolean[] array, int i, boolean val) { array[i] = val; } 1777 /** @hide */ arrayElementSetter(char[] array, int i, char val)1778 public static void arrayElementSetter(char[] array, int i, char val) { array[i] = val; } 1779 /** @hide */ arrayElementSetter(short[] array, int i, short val)1780 public static void arrayElementSetter(short[] array, int i, short val) { array[i] = val; } 1781 /** @hide */ arrayElementSetter(int[] array, int i, int val)1782 public static void arrayElementSetter(int[] array, int i, int val) { array[i] = val; } 1783 /** @hide */ arrayElementSetter(long[] array, int i, long val)1784 public static void arrayElementSetter(long[] array, int i, long val) { array[i] = val; } 1785 /** @hide */ arrayElementSetter(float[] array, int i, float val)1786 public static void arrayElementSetter(float[] array, int i, float val) { array[i] = val; } 1787 /** @hide */ arrayElementSetter(double[] array, int i, double val)1788 public static void arrayElementSetter(double[] array, int i, double val) { array[i] = val; } 1789 1790 1791 /// method handle invocation (reflective style) 1792 1793 /** 1794 * Produces a method handle which will invoke any method handle of the 1795 * given {@code type}, with a given number of trailing arguments replaced by 1796 * a single trailing {@code Object[]} array. 1797 * The resulting invoker will be a method handle with the following 1798 * arguments: 1799 * <ul> 1800 * <li>a single {@code MethodHandle} target 1801 * <li>zero or more leading values (counted by {@code leadingArgCount}) 1802 * <li>an {@code Object[]} array containing trailing arguments 1803 * </ul> 1804 * <p> 1805 * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with 1806 * the indicated {@code type}. 1807 * That is, if the target is exactly of the given {@code type}, it will behave 1808 * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType} 1809 * is used to convert the target to the required {@code type}. 1810 * <p> 1811 * The type of the returned invoker will not be the given {@code type}, but rather 1812 * will have all parameters except the first {@code leadingArgCount} 1813 * replaced by a single array of type {@code Object[]}, which will be 1814 * the final parameter. 1815 * <p> 1816 * Before invoking its target, the invoker will spread the final array, apply 1817 * reference casts as necessary, and unbox and widen primitive arguments. 1818 * If, when the invoker is called, the supplied array argument does 1819 * not have the correct number of elements, the invoker will throw 1820 * an {@link IllegalArgumentException} instead of invoking the target. 1821 * <p> 1822 * This method is equivalent to the following code (though it may be more efficient): 1823 * <blockquote><pre>{@code 1824 MethodHandle invoker = MethodHandles.invoker(type); 1825 int spreadArgCount = type.parameterCount() - leadingArgCount; 1826 invoker = invoker.asSpreader(Object[].class, spreadArgCount); 1827 return invoker; 1828 * }</pre></blockquote> 1829 * This method throws no reflective or security exceptions. 1830 * @param type the desired target type 1831 * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target 1832 * @return a method handle suitable for invoking any method handle of the given type 1833 * @throws NullPointerException if {@code type} is null 1834 * @throws IllegalArgumentException if {@code leadingArgCount} is not in 1835 * the range from 0 to {@code type.parameterCount()} inclusive, 1836 * or if the resulting method handle's type would have 1837 * <a href="MethodHandle.html#maxarity">too many parameters</a> 1838 */ 1839 static public spreadInvoker(MethodType type, int leadingArgCount)1840 MethodHandle spreadInvoker(MethodType type, int leadingArgCount) { 1841 if (leadingArgCount < 0 || leadingArgCount > type.parameterCount()) 1842 throw newIllegalArgumentException("bad argument count", leadingArgCount); 1843 1844 MethodHandle invoker = MethodHandles.invoker(type); 1845 int spreadArgCount = type.parameterCount() - leadingArgCount; 1846 invoker = invoker.asSpreader(Object[].class, spreadArgCount); 1847 return invoker; 1848 } 1849 1850 /** 1851 * Produces a special <em>invoker method handle</em> which can be used to 1852 * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}. 1853 * The resulting invoker will have a type which is 1854 * exactly equal to the desired type, except that it will accept 1855 * an additional leading argument of type {@code MethodHandle}. 1856 * <p> 1857 * This method is equivalent to the following code (though it may be more efficient): 1858 * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)} 1859 * 1860 * <p style="font-size:smaller;"> 1861 * <em>Discussion:</em> 1862 * Invoker method handles can be useful when working with variable method handles 1863 * of unknown types. 1864 * For example, to emulate an {@code invokeExact} call to a variable method 1865 * handle {@code M}, extract its type {@code T}, 1866 * look up the invoker method {@code X} for {@code T}, 1867 * and call the invoker method, as {@code X.invoke(T, A...)}. 1868 * (It would not work to call {@code X.invokeExact}, since the type {@code T} 1869 * is unknown.) 1870 * If spreading, collecting, or other argument transformations are required, 1871 * they can be applied once to the invoker {@code X} and reused on many {@code M} 1872 * method handle values, as long as they are compatible with the type of {@code X}. 1873 * <p style="font-size:smaller;"> 1874 * <em>(Note: The invoker method is not available via the Core Reflection API. 1875 * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} 1876 * on the declared {@code invokeExact} or {@code invoke} method will raise an 1877 * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> 1878 * <p> 1879 * This method throws no reflective or security exceptions. 1880 * @param type the desired target type 1881 * @return a method handle suitable for invoking any method handle of the given type 1882 * @throws IllegalArgumentException if the resulting method handle's type would have 1883 * <a href="MethodHandle.html#maxarity">too many parameters</a> 1884 */ 1885 static public exactInvoker(MethodType type)1886 MethodHandle exactInvoker(MethodType type) { 1887 return new Transformers.Invoker(type, true /* isExactInvoker */); 1888 } 1889 1890 /** 1891 * Produces a special <em>invoker method handle</em> which can be used to 1892 * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}. 1893 * The resulting invoker will have a type which is 1894 * exactly equal to the desired type, except that it will accept 1895 * an additional leading argument of type {@code MethodHandle}. 1896 * <p> 1897 * Before invoking its target, if the target differs from the expected type, 1898 * the invoker will apply reference casts as 1899 * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}. 1900 * Similarly, the return value will be converted as necessary. 1901 * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle}, 1902 * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}. 1903 * <p> 1904 * This method is equivalent to the following code (though it may be more efficient): 1905 * {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)} 1906 * <p style="font-size:smaller;"> 1907 * <em>Discussion:</em> 1908 * A {@linkplain MethodType#genericMethodType general method type} is one which 1909 * mentions only {@code Object} arguments and return values. 1910 * An invoker for such a type is capable of calling any method handle 1911 * of the same arity as the general type. 1912 * <p style="font-size:smaller;"> 1913 * <em>(Note: The invoker method is not available via the Core Reflection API. 1914 * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} 1915 * on the declared {@code invokeExact} or {@code invoke} method will raise an 1916 * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> 1917 * <p> 1918 * This method throws no reflective or security exceptions. 1919 * @param type the desired target type 1920 * @return a method handle suitable for invoking any method handle convertible to the given type 1921 * @throws IllegalArgumentException if the resulting method handle's type would have 1922 * <a href="MethodHandle.html#maxarity">too many parameters</a> 1923 */ 1924 static public invoker(MethodType type)1925 MethodHandle invoker(MethodType type) { 1926 return new Transformers.Invoker(type, false /* isExactInvoker */); 1927 } 1928 1929 // Android-changed: Basic invokers are not supported. 1930 // 1931 // static /*non-public*/ 1932 // MethodHandle basicInvoker(MethodType type) { 1933 // return type.invokers().basicInvoker(); 1934 // } 1935 1936 /// method handle modification (creation from other method handles) 1937 1938 /** 1939 * Produces a method handle which adapts the type of the 1940 * given method handle to a new type by pairwise argument and return type conversion. 1941 * The original type and new type must have the same number of arguments. 1942 * The resulting method handle is guaranteed to report a type 1943 * which is equal to the desired new type. 1944 * <p> 1945 * If the original type and new type are equal, returns target. 1946 * <p> 1947 * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType}, 1948 * and some additional conversions are also applied if those conversions fail. 1949 * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied 1950 * if possible, before or instead of any conversions done by {@code asType}: 1951 * <ul> 1952 * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type, 1953 * then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast. 1954 * (This treatment of interfaces follows the usage of the bytecode verifier.) 1955 * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive, 1956 * the boolean is converted to a byte value, 1 for true, 0 for false. 1957 * (This treatment follows the usage of the bytecode verifier.) 1958 * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive, 1959 * <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5), 1960 * and the low order bit of the result is tested, as if by {@code (x & 1) != 0}. 1961 * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean, 1962 * then a Java casting conversion (JLS 5.5) is applied. 1963 * (Specifically, <em>T0</em> will convert to <em>T1</em> by 1964 * widening and/or narrowing.) 1965 * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing 1966 * conversion will be applied at runtime, possibly followed 1967 * by a Java casting conversion (JLS 5.5) on the primitive value, 1968 * possibly followed by a conversion from byte to boolean by testing 1969 * the low-order bit. 1970 * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, 1971 * and if the reference is null at runtime, a zero value is introduced. 1972 * </ul> 1973 * @param target the method handle to invoke after arguments are retyped 1974 * @param newType the expected type of the new method handle 1975 * @return a method handle which delegates to the target after performing 1976 * any necessary argument conversions, and arranges for any 1977 * necessary return value conversions 1978 * @throws NullPointerException if either argument is null 1979 * @throws WrongMethodTypeException if the conversion cannot be made 1980 * @see MethodHandle#asType 1981 */ 1982 public static explicitCastArguments(MethodHandle target, MethodType newType)1983 MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { 1984 explicitCastArgumentsChecks(target, newType); 1985 // use the asTypeCache when possible: 1986 MethodType oldType = target.type(); 1987 if (oldType == newType) return target; 1988 if (oldType.explicitCastEquivalentToAsType(newType)) { 1989 return target.asFixedArity().asType(newType); 1990 } 1991 1992 return new Transformers.ExplicitCastArguments(target, newType); 1993 } 1994 explicitCastArgumentsChecks(MethodHandle target, MethodType newType)1995 private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) { 1996 if (target.type().parameterCount() != newType.parameterCount()) { 1997 throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType); 1998 } 1999 } 2000 2001 /** 2002 * Produces a method handle which adapts the calling sequence of the 2003 * given method handle to a new type, by reordering the arguments. 2004 * The resulting method handle is guaranteed to report a type 2005 * which is equal to the desired new type. 2006 * <p> 2007 * The given array controls the reordering. 2008 * Call {@code #I} the number of incoming parameters (the value 2009 * {@code newType.parameterCount()}, and call {@code #O} the number 2010 * of outgoing parameters (the value {@code target.type().parameterCount()}). 2011 * Then the length of the reordering array must be {@code #O}, 2012 * and each element must be a non-negative number less than {@code #I}. 2013 * For every {@code N} less than {@code #O}, the {@code N}-th 2014 * outgoing argument will be taken from the {@code I}-th incoming 2015 * argument, where {@code I} is {@code reorder[N]}. 2016 * <p> 2017 * No argument or return value conversions are applied. 2018 * The type of each incoming argument, as determined by {@code newType}, 2019 * must be identical to the type of the corresponding outgoing parameter 2020 * or parameters in the target method handle. 2021 * The return type of {@code newType} must be identical to the return 2022 * type of the original target. 2023 * <p> 2024 * The reordering array need not specify an actual permutation. 2025 * An incoming argument will be duplicated if its index appears 2026 * more than once in the array, and an incoming argument will be dropped 2027 * if its index does not appear in the array. 2028 * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, 2029 * incoming arguments which are not mentioned in the reordering array 2030 * are may be any type, as determined only by {@code newType}. 2031 * <blockquote><pre>{@code 2032 import static java.lang.invoke.MethodHandles.*; 2033 import static java.lang.invoke.MethodType.*; 2034 ... 2035 MethodType intfn1 = methodType(int.class, int.class); 2036 MethodType intfn2 = methodType(int.class, int.class, int.class); 2037 MethodHandle sub = ... (int x, int y) -> (x-y) ...; 2038 assert(sub.type().equals(intfn2)); 2039 MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1); 2040 MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0); 2041 assert((int)rsub.invokeExact(1, 100) == 99); 2042 MethodHandle add = ... (int x, int y) -> (x+y) ...; 2043 assert(add.type().equals(intfn2)); 2044 MethodHandle twice = permuteArguments(add, intfn1, 0, 0); 2045 assert(twice.type().equals(intfn1)); 2046 assert((int)twice.invokeExact(21) == 42); 2047 * }</pre></blockquote> 2048 * @param target the method handle to invoke after arguments are reordered 2049 * @param newType the expected type of the new method handle 2050 * @param reorder an index array which controls the reordering 2051 * @return a method handle which delegates to the target after it 2052 * drops unused arguments and moves and/or duplicates the other arguments 2053 * @throws NullPointerException if any argument is null 2054 * @throws IllegalArgumentException if the index array length is not equal to 2055 * the arity of the target, or if any index array element 2056 * not a valid index for a parameter of {@code newType}, 2057 * or if two corresponding parameter types in 2058 * {@code target.type()} and {@code newType} are not identical, 2059 */ 2060 public static permuteArguments(MethodHandle target, MethodType newType, int... reorder)2061 MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { 2062 reorder = reorder.clone(); // get a private copy 2063 MethodType oldType = target.type(); 2064 permuteArgumentChecks(reorder, newType, oldType); 2065 2066 return new Transformers.PermuteArguments(newType, target, reorder); 2067 } 2068 2069 // Android-changed: findFirstDupOrDrop is unused and removed. 2070 // private static int findFirstDupOrDrop(int[] reorder, int newArity); 2071 permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType)2072 private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) { 2073 if (newType.returnType() != oldType.returnType()) 2074 throw newIllegalArgumentException("return types do not match", 2075 oldType, newType); 2076 if (reorder.length == oldType.parameterCount()) { 2077 int limit = newType.parameterCount(); 2078 boolean bad = false; 2079 for (int j = 0; j < reorder.length; j++) { 2080 int i = reorder[j]; 2081 if (i < 0 || i >= limit) { 2082 bad = true; break; 2083 } 2084 Class<?> src = newType.parameterType(i); 2085 Class<?> dst = oldType.parameterType(j); 2086 if (src != dst) 2087 throw newIllegalArgumentException("parameter types do not match after reorder", 2088 oldType, newType); 2089 } 2090 if (!bad) return true; 2091 } 2092 throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); 2093 } 2094 2095 /** 2096 * Produces a method handle of the requested return type which returns the given 2097 * constant value every time it is invoked. 2098 * <p> 2099 * Before the method handle is returned, the passed-in value is converted to the requested type. 2100 * If the requested type is primitive, widening primitive conversions are attempted, 2101 * else reference conversions are attempted. 2102 * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}. 2103 * @param type the return type of the desired method handle 2104 * @param value the value to return 2105 * @return a method handle of the given return type and no arguments, which always returns the given value 2106 * @throws NullPointerException if the {@code type} argument is null 2107 * @throws ClassCastException if the value cannot be converted to the required return type 2108 * @throws IllegalArgumentException if the given type is {@code void.class} 2109 */ 2110 public static constant(Class<?> type, Object value)2111 MethodHandle constant(Class<?> type, Object value) { 2112 if (type.isPrimitive()) { 2113 if (type == void.class) 2114 throw newIllegalArgumentException("void type"); 2115 Wrapper w = Wrapper.forPrimitiveType(type); 2116 value = w.convert(value, type); 2117 } 2118 2119 return new Transformers.Constant(type, value); 2120 } 2121 2122 /** 2123 * Produces a method handle which returns its sole argument when invoked. 2124 * @param type the type of the sole parameter and return value of the desired method handle 2125 * @return a unary method handle which accepts and returns the given type 2126 * @throws NullPointerException if the argument is null 2127 * @throws IllegalArgumentException if the given type is {@code void.class} 2128 */ 2129 public static identity(Class<?> type)2130 MethodHandle identity(Class<?> type) { 2131 if (type == null) { 2132 throw new NullPointerException("type == null"); 2133 } 2134 2135 if (type.isPrimitive()) { 2136 try { 2137 return Lookup.PUBLIC_LOOKUP.findStatic(MethodHandles.class, "identity", 2138 MethodType.methodType(type, type)); 2139 } catch (NoSuchMethodException | IllegalAccessException e) { 2140 throw new AssertionError(e); 2141 } 2142 } 2143 2144 return new Transformers.ReferenceIdentity(type); 2145 } 2146 identity(byte val)2147 /** @hide */ public static byte identity(byte val) { return val; } identity(boolean val)2148 /** @hide */ public static boolean identity(boolean val) { return val; } identity(char val)2149 /** @hide */ public static char identity(char val) { return val; } identity(short val)2150 /** @hide */ public static short identity(short val) { return val; } identity(int val)2151 /** @hide */ public static int identity(int val) { return val; } identity(long val)2152 /** @hide */ public static long identity(long val) { return val; } identity(float val)2153 /** @hide */ public static float identity(float val) { return val; } identity(double val)2154 /** @hide */ public static double identity(double val) { return val; } 2155 2156 /** 2157 * Provides a target method handle with one or more <em>bound arguments</em> 2158 * in advance of the method handle's invocation. 2159 * The formal parameters to the target corresponding to the bound 2160 * arguments are called <em>bound parameters</em>. 2161 * Returns a new method handle which saves away the bound arguments. 2162 * When it is invoked, it receives arguments for any non-bound parameters, 2163 * binds the saved arguments to their corresponding parameters, 2164 * and calls the original target. 2165 * <p> 2166 * The type of the new method handle will drop the types for the bound 2167 * parameters from the original target type, since the new method handle 2168 * will no longer require those arguments to be supplied by its callers. 2169 * <p> 2170 * Each given argument object must match the corresponding bound parameter type. 2171 * If a bound parameter type is a primitive, the argument object 2172 * must be a wrapper, and will be unboxed to produce the primitive value. 2173 * <p> 2174 * The {@code pos} argument selects which parameters are to be bound. 2175 * It may range between zero and <i>N-L</i> (inclusively), 2176 * where <i>N</i> is the arity of the target method handle 2177 * and <i>L</i> is the length of the values array. 2178 * @param target the method handle to invoke after the argument is inserted 2179 * @param pos where to insert the argument (zero for the first) 2180 * @param values the series of arguments to insert 2181 * @return a method handle which inserts an additional argument, 2182 * before calling the original method handle 2183 * @throws NullPointerException if the target or the {@code values} array is null 2184 * @see MethodHandle#bindTo 2185 */ 2186 public static insertArguments(MethodHandle target, int pos, Object... values)2187 MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { 2188 int insCount = values.length; 2189 Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos); 2190 if (insCount == 0) { 2191 return target; 2192 } 2193 2194 // Throw ClassCastExceptions early if we can't cast any of the provided values 2195 // to the required type. 2196 for (int i = 0; i < insCount; i++) { 2197 final Class<?> ptype = ptypes[pos + i]; 2198 if (!ptype.isPrimitive()) { 2199 ptypes[pos + i].cast(values[i]); 2200 } else { 2201 // Will throw a ClassCastException if something terrible happens. 2202 values[i] = Wrapper.forPrimitiveType(ptype).convert(values[i], ptype); 2203 } 2204 } 2205 2206 return new Transformers.InsertArguments(target, pos, values); 2207 } 2208 2209 // Android-changed: insertArgumentPrimitive is unused. 2210 // 2211 // private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos, 2212 // Class<?> ptype, Object value) { 2213 // Wrapper w = Wrapper.forPrimitiveType(ptype); 2214 // // perform unboxing and/or primitive conversion 2215 // value = w.convert(value, ptype); 2216 // switch (w) { 2217 // case INT: return result.bindArgumentI(pos, (int)value); 2218 // case LONG: return result.bindArgumentJ(pos, (long)value); 2219 // case FLOAT: return result.bindArgumentF(pos, (float)value); 2220 // case DOUBLE: return result.bindArgumentD(pos, (double)value); 2221 // default: return result.bindArgumentI(pos, ValueConversions.widenSubword(value)); 2222 // } 2223 // } 2224 insertArgumentsChecks(MethodHandle target, int insCount, int pos)2225 private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException { 2226 MethodType oldType = target.type(); 2227 int outargs = oldType.parameterCount(); 2228 int inargs = outargs - insCount; 2229 if (inargs < 0) 2230 throw newIllegalArgumentException("too many values to insert"); 2231 if (pos < 0 || pos > inargs) 2232 throw newIllegalArgumentException("no argument type to append"); 2233 return oldType.ptypes(); 2234 } 2235 2236 /** 2237 * Produces a method handle which will discard some dummy arguments 2238 * before calling some other specified <i>target</i> method handle. 2239 * The type of the new method handle will be the same as the target's type, 2240 * except it will also include the dummy argument types, 2241 * at some given position. 2242 * <p> 2243 * The {@code pos} argument may range between zero and <i>N</i>, 2244 * where <i>N</i> is the arity of the target. 2245 * If {@code pos} is zero, the dummy arguments will precede 2246 * the target's real arguments; if {@code pos} is <i>N</i> 2247 * they will come after. 2248 * <p> 2249 * <b>Example:</b> 2250 * <blockquote><pre>{@code 2251 import static java.lang.invoke.MethodHandles.*; 2252 import static java.lang.invoke.MethodType.*; 2253 ... 2254 MethodHandle cat = lookup().findVirtual(String.class, 2255 "concat", methodType(String.class, String.class)); 2256 assertEquals("xy", (String) cat.invokeExact("x", "y")); 2257 MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class); 2258 MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2)); 2259 assertEquals(bigType, d0.type()); 2260 assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); 2261 * }</pre></blockquote> 2262 * <p> 2263 * This method is also equivalent to the following code: 2264 * <blockquote><pre> 2265 * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))} 2266 * </pre></blockquote> 2267 * @param target the method handle to invoke after the arguments are dropped 2268 * @param valueTypes the type(s) of the argument(s) to drop 2269 * @param pos position of first argument to drop (zero for the leftmost) 2270 * @return a method handle which drops arguments of the given types, 2271 * before calling the original method handle 2272 * @throws NullPointerException if the target is null, 2273 * or if the {@code valueTypes} list or any of its elements is null 2274 * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, 2275 * or if {@code pos} is negative or greater than the arity of the target, 2276 * or if the new method handle's type would have too many parameters 2277 */ 2278 public static dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes)2279 MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { 2280 valueTypes = copyTypes(valueTypes); 2281 MethodType oldType = target.type(); // get NPE 2282 int dropped = dropArgumentChecks(oldType, pos, valueTypes); 2283 2284 MethodType newType = oldType.insertParameterTypes(pos, valueTypes); 2285 if (dropped == 0) { 2286 return target; 2287 } 2288 2289 return new Transformers.DropArguments(newType, target, pos, valueTypes.size()); 2290 } 2291 copyTypes(List<Class<?>> types)2292 private static List<Class<?>> copyTypes(List<Class<?>> types) { 2293 Object[] a = types.toArray(); 2294 return Arrays.asList(Arrays.copyOf(a, a.length, Class[].class)); 2295 } 2296 dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes)2297 private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) { 2298 int dropped = valueTypes.size(); 2299 MethodType.checkSlotCount(dropped); 2300 int outargs = oldType.parameterCount(); 2301 int inargs = outargs + dropped; 2302 if (pos < 0 || pos > outargs) 2303 throw newIllegalArgumentException("no argument type to remove" 2304 + Arrays.asList(oldType, pos, valueTypes, inargs, outargs) 2305 ); 2306 return dropped; 2307 } 2308 2309 /** 2310 * Produces a method handle which will discard some dummy arguments 2311 * before calling some other specified <i>target</i> method handle. 2312 * The type of the new method handle will be the same as the target's type, 2313 * except it will also include the dummy argument types, 2314 * at some given position. 2315 * <p> 2316 * The {@code pos} argument may range between zero and <i>N</i>, 2317 * where <i>N</i> is the arity of the target. 2318 * If {@code pos} is zero, the dummy arguments will precede 2319 * the target's real arguments; if {@code pos} is <i>N</i> 2320 * they will come after. 2321 * <p> 2322 * <b>Example:</b> 2323 * <blockquote><pre>{@code 2324 import static java.lang.invoke.MethodHandles.*; 2325 import static java.lang.invoke.MethodType.*; 2326 ... 2327 MethodHandle cat = lookup().findVirtual(String.class, 2328 "concat", methodType(String.class, String.class)); 2329 assertEquals("xy", (String) cat.invokeExact("x", "y")); 2330 MethodHandle d0 = dropArguments(cat, 0, String.class); 2331 assertEquals("yz", (String) d0.invokeExact("x", "y", "z")); 2332 MethodHandle d1 = dropArguments(cat, 1, String.class); 2333 assertEquals("xz", (String) d1.invokeExact("x", "y", "z")); 2334 MethodHandle d2 = dropArguments(cat, 2, String.class); 2335 assertEquals("xy", (String) d2.invokeExact("x", "y", "z")); 2336 MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); 2337 assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); 2338 * }</pre></blockquote> 2339 * <p> 2340 * This method is also equivalent to the following code: 2341 * <blockquote><pre> 2342 * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))} 2343 * </pre></blockquote> 2344 * @param target the method handle to invoke after the arguments are dropped 2345 * @param valueTypes the type(s) of the argument(s) to drop 2346 * @param pos position of first argument to drop (zero for the leftmost) 2347 * @return a method handle which drops arguments of the given types, 2348 * before calling the original method handle 2349 * @throws NullPointerException if the target is null, 2350 * or if the {@code valueTypes} array or any of its elements is null 2351 * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, 2352 * or if {@code pos} is negative or greater than the arity of the target, 2353 * or if the new method handle's type would have 2354 * <a href="MethodHandle.html#maxarity">too many parameters</a> 2355 */ 2356 public static dropArguments(MethodHandle target, int pos, Class<?>... valueTypes)2357 MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) { 2358 return dropArguments(target, pos, Arrays.asList(valueTypes)); 2359 } 2360 2361 /** 2362 * Adapts a target method handle by pre-processing 2363 * one or more of its arguments, each with its own unary filter function, 2364 * and then calling the target with each pre-processed argument 2365 * replaced by the result of its corresponding filter function. 2366 * <p> 2367 * The pre-processing is performed by one or more method handles, 2368 * specified in the elements of the {@code filters} array. 2369 * The first element of the filter array corresponds to the {@code pos} 2370 * argument of the target, and so on in sequence. 2371 * <p> 2372 * Null arguments in the array are treated as identity functions, 2373 * and the corresponding arguments left unchanged. 2374 * (If there are no non-null elements in the array, the original target is returned.) 2375 * Each filter is applied to the corresponding argument of the adapter. 2376 * <p> 2377 * If a filter {@code F} applies to the {@code N}th argument of 2378 * the target, then {@code F} must be a method handle which 2379 * takes exactly one argument. The type of {@code F}'s sole argument 2380 * replaces the corresponding argument type of the target 2381 * in the resulting adapted method handle. 2382 * The return type of {@code F} must be identical to the corresponding 2383 * parameter type of the target. 2384 * <p> 2385 * It is an error if there are elements of {@code filters} 2386 * (null or not) 2387 * which do not correspond to argument positions in the target. 2388 * <p><b>Example:</b> 2389 * <blockquote><pre>{@code 2390 import static java.lang.invoke.MethodHandles.*; 2391 import static java.lang.invoke.MethodType.*; 2392 ... 2393 MethodHandle cat = lookup().findVirtual(String.class, 2394 "concat", methodType(String.class, String.class)); 2395 MethodHandle upcase = lookup().findVirtual(String.class, 2396 "toUpperCase", methodType(String.class)); 2397 assertEquals("xy", (String) cat.invokeExact("x", "y")); 2398 MethodHandle f0 = filterArguments(cat, 0, upcase); 2399 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy 2400 MethodHandle f1 = filterArguments(cat, 1, upcase); 2401 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY 2402 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); 2403 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY 2404 * }</pre></blockquote> 2405 * <p> Here is pseudocode for the resulting adapter: 2406 * <blockquote><pre>{@code 2407 * V target(P... p, A[i]... a[i], B... b); 2408 * A[i] filter[i](V[i]); 2409 * T adapter(P... p, V[i]... v[i], B... b) { 2410 * return target(p..., f[i](v[i])..., b...); 2411 * } 2412 * }</pre></blockquote> 2413 * 2414 * @param target the method handle to invoke after arguments are filtered 2415 * @param pos the position of the first argument to filter 2416 * @param filters method handles to call initially on filtered arguments 2417 * @return method handle which incorporates the specified argument filtering logic 2418 * @throws NullPointerException if the target is null 2419 * or if the {@code filters} array is null 2420 * @throws IllegalArgumentException if a non-null element of {@code filters} 2421 * does not match a corresponding argument type of target as described above, 2422 * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}, 2423 * or if the resulting method handle's type would have 2424 * <a href="MethodHandle.html#maxarity">too many parameters</a> 2425 */ 2426 public static filterArguments(MethodHandle target, int pos, MethodHandle... filters)2427 MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { 2428 filterArgumentsCheckArity(target, pos, filters); 2429 2430 for (int i = 0; i < filters.length; ++i) { 2431 filterArgumentChecks(target, i + pos, filters[i]); 2432 } 2433 2434 return new Transformers.FilterArguments(target, pos, filters); 2435 } 2436 filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters)2437 private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) { 2438 MethodType targetType = target.type(); 2439 int maxPos = targetType.parameterCount(); 2440 if (pos + filters.length > maxPos) 2441 throw newIllegalArgumentException("too many filters"); 2442 } 2443 filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter)2444 private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { 2445 MethodType targetType = target.type(); 2446 MethodType filterType = filter.type(); 2447 if (filterType.parameterCount() != 1 2448 || filterType.returnType() != targetType.parameterType(pos)) 2449 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); 2450 } 2451 2452 /** 2453 * Adapts a target method handle by pre-processing 2454 * a sub-sequence of its arguments with a filter (another method handle). 2455 * The pre-processed arguments are replaced by the result (if any) of the 2456 * filter function. 2457 * The target is then called on the modified (usually shortened) argument list. 2458 * <p> 2459 * If the filter returns a value, the target must accept that value as 2460 * its argument in position {@code pos}, preceded and/or followed by 2461 * any arguments not passed to the filter. 2462 * If the filter returns void, the target must accept all arguments 2463 * not passed to the filter. 2464 * No arguments are reordered, and a result returned from the filter 2465 * replaces (in order) the whole subsequence of arguments originally 2466 * passed to the adapter. 2467 * <p> 2468 * The argument types (if any) of the filter 2469 * replace zero or one argument types of the target, at position {@code pos}, 2470 * in the resulting adapted method handle. 2471 * The return type of the filter (if any) must be identical to the 2472 * argument type of the target at position {@code pos}, and that target argument 2473 * is supplied by the return value of the filter. 2474 * <p> 2475 * In all cases, {@code pos} must be greater than or equal to zero, and 2476 * {@code pos} must also be less than or equal to the target's arity. 2477 * <p><b>Example:</b> 2478 * <blockquote><pre>{@code 2479 import static java.lang.invoke.MethodHandles.*; 2480 import static java.lang.invoke.MethodType.*; 2481 ... 2482 MethodHandle deepToString = publicLookup() 2483 .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class)); 2484 2485 MethodHandle ts1 = deepToString.asCollector(String[].class, 1); 2486 assertEquals("[strange]", (String) ts1.invokeExact("strange")); 2487 2488 MethodHandle ts2 = deepToString.asCollector(String[].class, 2); 2489 assertEquals("[up, down]", (String) ts2.invokeExact("up", "down")); 2490 2491 MethodHandle ts3 = deepToString.asCollector(String[].class, 3); 2492 MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2); 2493 assertEquals("[top, [up, down], strange]", 2494 (String) ts3_ts2.invokeExact("top", "up", "down", "strange")); 2495 2496 MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1); 2497 assertEquals("[top, [up, down], [strange]]", 2498 (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange")); 2499 2500 MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); 2501 assertEquals("[top, [[up, down, strange], charm], bottom]", 2502 (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom")); 2503 * }</pre></blockquote> 2504 * <p> Here is pseudocode for the resulting adapter: 2505 * <blockquote><pre>{@code 2506 * T target(A...,V,C...); 2507 * V filter(B...); 2508 * T adapter(A... a,B... b,C... c) { 2509 * V v = filter(b...); 2510 * return target(a...,v,c...); 2511 * } 2512 * // and if the filter has no arguments: 2513 * T target2(A...,V,C...); 2514 * V filter2(); 2515 * T adapter2(A... a,C... c) { 2516 * V v = filter2(); 2517 * return target2(a...,v,c...); 2518 * } 2519 * // and if the filter has a void return: 2520 * T target3(A...,C...); 2521 * void filter3(B...); 2522 * void adapter3(A... a,B... b,C... c) { 2523 * filter3(b...); 2524 * return target3(a...,c...); 2525 * } 2526 * }</pre></blockquote> 2527 * <p> 2528 * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to 2529 * one which first "folds" the affected arguments, and then drops them, in separate 2530 * steps as follows: 2531 * <blockquote><pre>{@code 2532 * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2 2533 * mh = MethodHandles.foldArguments(mh, coll); //step 1 2534 * }</pre></blockquote> 2535 * If the target method handle consumes no arguments besides than the result 2536 * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)} 2537 * is equivalent to {@code filterReturnValue(coll, mh)}. 2538 * If the filter method handle {@code coll} consumes one argument and produces 2539 * a non-void result, then {@code collectArguments(mh, N, coll)} 2540 * is equivalent to {@code filterArguments(mh, N, coll)}. 2541 * Other equivalences are possible but would require argument permutation. 2542 * 2543 * @param target the method handle to invoke after filtering the subsequence of arguments 2544 * @param pos the position of the first adapter argument to pass to the filter, 2545 * and/or the target argument which receives the result of the filter 2546 * @param filter method handle to call on the subsequence of arguments 2547 * @return method handle which incorporates the specified argument subsequence filtering logic 2548 * @throws NullPointerException if either argument is null 2549 * @throws IllegalArgumentException if the return type of {@code filter} 2550 * is non-void and is not the same as the {@code pos} argument of the target, 2551 * or if {@code pos} is not between 0 and the target's arity, inclusive, 2552 * or if the resulting method handle's type would have 2553 * <a href="MethodHandle.html#maxarity">too many parameters</a> 2554 * @see MethodHandles#foldArguments 2555 * @see MethodHandles#filterArguments 2556 * @see MethodHandles#filterReturnValue 2557 */ 2558 public static collectArguments(MethodHandle target, int pos, MethodHandle filter)2559 MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) { 2560 MethodType newType = collectArgumentsChecks(target, pos, filter); 2561 return new Transformers.CollectArguments(target, filter, pos, newType); 2562 } 2563 collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter)2564 private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { 2565 MethodType targetType = target.type(); 2566 MethodType filterType = filter.type(); 2567 Class<?> rtype = filterType.returnType(); 2568 List<Class<?>> filterArgs = filterType.parameterList(); 2569 if (rtype == void.class) { 2570 return targetType.insertParameterTypes(pos, filterArgs); 2571 } 2572 if (rtype != targetType.parameterType(pos)) { 2573 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); 2574 } 2575 return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs); 2576 } 2577 2578 /** 2579 * Adapts a target method handle by post-processing 2580 * its return value (if any) with a filter (another method handle). 2581 * The result of the filter is returned from the adapter. 2582 * <p> 2583 * If the target returns a value, the filter must accept that value as 2584 * its only argument. 2585 * If the target returns void, the filter must accept no arguments. 2586 * <p> 2587 * The return type of the filter 2588 * replaces the return type of the target 2589 * in the resulting adapted method handle. 2590 * The argument type of the filter (if any) must be identical to the 2591 * return type of the target. 2592 * <p><b>Example:</b> 2593 * <blockquote><pre>{@code 2594 import static java.lang.invoke.MethodHandles.*; 2595 import static java.lang.invoke.MethodType.*; 2596 ... 2597 MethodHandle cat = lookup().findVirtual(String.class, 2598 "concat", methodType(String.class, String.class)); 2599 MethodHandle length = lookup().findVirtual(String.class, 2600 "length", methodType(int.class)); 2601 System.out.println((String) cat.invokeExact("x", "y")); // xy 2602 MethodHandle f0 = filterReturnValue(cat, length); 2603 System.out.println((int) f0.invokeExact("x", "y")); // 2 2604 * }</pre></blockquote> 2605 * <p> Here is pseudocode for the resulting adapter: 2606 * <blockquote><pre>{@code 2607 * V target(A...); 2608 * T filter(V); 2609 * T adapter(A... a) { 2610 * V v = target(a...); 2611 * return filter(v); 2612 * } 2613 * // and if the target has a void return: 2614 * void target2(A...); 2615 * T filter2(); 2616 * T adapter2(A... a) { 2617 * target2(a...); 2618 * return filter2(); 2619 * } 2620 * // and if the filter has a void return: 2621 * V target3(A...); 2622 * void filter3(V); 2623 * void adapter3(A... a) { 2624 * V v = target3(a...); 2625 * filter3(v); 2626 * } 2627 * }</pre></blockquote> 2628 * @param target the method handle to invoke before filtering the return value 2629 * @param filter method handle to call on the return value 2630 * @return method handle which incorporates the specified return value filtering logic 2631 * @throws NullPointerException if either argument is null 2632 * @throws IllegalArgumentException if the argument list of {@code filter} 2633 * does not match the return type of target as described above 2634 */ 2635 public static filterReturnValue(MethodHandle target, MethodHandle filter)2636 MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { 2637 MethodType targetType = target.type(); 2638 MethodType filterType = filter.type(); 2639 filterReturnValueChecks(targetType, filterType); 2640 2641 return new Transformers.FilterReturnValue(target, filter); 2642 } 2643 filterReturnValueChecks(MethodType targetType, MethodType filterType)2644 private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException { 2645 Class<?> rtype = targetType.returnType(); 2646 int filterValues = filterType.parameterCount(); 2647 if (filterValues == 0 2648 ? (rtype != void.class) 2649 : (rtype != filterType.parameterType(0) || filterValues != 1)) 2650 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); 2651 } 2652 2653 /** 2654 * Adapts a target method handle by pre-processing 2655 * some of its arguments, and then calling the target with 2656 * the result of the pre-processing, inserted into the original 2657 * sequence of arguments. 2658 * <p> 2659 * The pre-processing is performed by {@code combiner}, a second method handle. 2660 * Of the arguments passed to the adapter, the first {@code N} arguments 2661 * are copied to the combiner, which is then called. 2662 * (Here, {@code N} is defined as the parameter count of the combiner.) 2663 * After this, control passes to the target, with any result 2664 * from the combiner inserted before the original {@code N} incoming 2665 * arguments. 2666 * <p> 2667 * If the combiner returns a value, the first parameter type of the target 2668 * must be identical with the return type of the combiner, and the next 2669 * {@code N} parameter types of the target must exactly match the parameters 2670 * of the combiner. 2671 * <p> 2672 * If the combiner has a void return, no result will be inserted, 2673 * and the first {@code N} parameter types of the target 2674 * must exactly match the parameters of the combiner. 2675 * <p> 2676 * The resulting adapter is the same type as the target, except that the 2677 * first parameter type is dropped, 2678 * if it corresponds to the result of the combiner. 2679 * <p> 2680 * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments 2681 * that either the combiner or the target does not wish to receive. 2682 * If some of the incoming arguments are destined only for the combiner, 2683 * consider using {@link MethodHandle#asCollector asCollector} instead, since those 2684 * arguments will not need to be live on the stack on entry to the 2685 * target.) 2686 * <p><b>Example:</b> 2687 * <blockquote><pre>{@code 2688 import static java.lang.invoke.MethodHandles.*; 2689 import static java.lang.invoke.MethodType.*; 2690 ... 2691 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class, 2692 "println", methodType(void.class, String.class)) 2693 .bindTo(System.out); 2694 MethodHandle cat = lookup().findVirtual(String.class, 2695 "concat", methodType(String.class, String.class)); 2696 assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); 2697 MethodHandle catTrace = foldArguments(cat, trace); 2698 // also prints "boo": 2699 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); 2700 * }</pre></blockquote> 2701 * <p> Here is pseudocode for the resulting adapter: 2702 * <blockquote><pre>{@code 2703 * // there are N arguments in A... 2704 * T target(V, A[N]..., B...); 2705 * V combiner(A...); 2706 * T adapter(A... a, B... b) { 2707 * V v = combiner(a...); 2708 * return target(v, a..., b...); 2709 * } 2710 * // and if the combiner has a void return: 2711 * T target2(A[N]..., B...); 2712 * void combiner2(A...); 2713 * T adapter2(A... a, B... b) { 2714 * combiner2(a...); 2715 * return target2(a..., b...); 2716 * } 2717 * }</pre></blockquote> 2718 * @param target the method handle to invoke after arguments are combined 2719 * @param combiner method handle to call initially on the incoming arguments 2720 * @return method handle which incorporates the specified argument folding logic 2721 * @throws NullPointerException if either argument is null 2722 * @throws IllegalArgumentException if {@code combiner}'s return type 2723 * is non-void and not the same as the first argument type of 2724 * the target, or if the initial {@code N} argument types 2725 * of the target 2726 * (skipping one matching the {@code combiner}'s return type) 2727 * are not identical with the argument types of {@code combiner} 2728 */ 2729 public static foldArguments(MethodHandle target, MethodHandle combiner)2730 MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { 2731 int foldPos = 0; 2732 MethodType targetType = target.type(); 2733 MethodType combinerType = combiner.type(); 2734 Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType); 2735 2736 return new Transformers.FoldArguments(target, combiner); 2737 } 2738 foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType)2739 private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) { 2740 int foldArgs = combinerType.parameterCount(); 2741 Class<?> rtype = combinerType.returnType(); 2742 int foldVals = rtype == void.class ? 0 : 1; 2743 int afterInsertPos = foldPos + foldVals; 2744 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs); 2745 if (ok && !(combinerType.parameterList() 2746 .equals(targetType.parameterList().subList(afterInsertPos, 2747 afterInsertPos + foldArgs)))) 2748 ok = false; 2749 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0)) 2750 ok = false; 2751 if (!ok) 2752 throw misMatchedTypes("target and combiner types", targetType, combinerType); 2753 return rtype; 2754 } 2755 2756 /** 2757 * Makes a method handle which adapts a target method handle, 2758 * by guarding it with a test, a boolean-valued method handle. 2759 * If the guard fails, a fallback handle is called instead. 2760 * All three method handles must have the same corresponding 2761 * argument and return types, except that the return type 2762 * of the test must be boolean, and the test is allowed 2763 * to have fewer arguments than the other two method handles. 2764 * <p> Here is pseudocode for the resulting adapter: 2765 * <blockquote><pre>{@code 2766 * boolean test(A...); 2767 * T target(A...,B...); 2768 * T fallback(A...,B...); 2769 * T adapter(A... a,B... b) { 2770 * if (test(a...)) 2771 * return target(a..., b...); 2772 * else 2773 * return fallback(a..., b...); 2774 * } 2775 * }</pre></blockquote> 2776 * Note that the test arguments ({@code a...} in the pseudocode) cannot 2777 * be modified by execution of the test, and so are passed unchanged 2778 * from the caller to the target or fallback as appropriate. 2779 * @param test method handle used for test, must return boolean 2780 * @param target method handle to call if test passes 2781 * @param fallback method handle to call if test fails 2782 * @return method handle which incorporates the specified if/then/else logic 2783 * @throws NullPointerException if any argument is null 2784 * @throws IllegalArgumentException if {@code test} does not return boolean, 2785 * or if all three method types do not match (with the return 2786 * type of {@code test} changed to match that of the target). 2787 */ 2788 public static guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback)2789 MethodHandle guardWithTest(MethodHandle test, 2790 MethodHandle target, 2791 MethodHandle fallback) { 2792 MethodType gtype = test.type(); 2793 MethodType ttype = target.type(); 2794 MethodType ftype = fallback.type(); 2795 if (!ttype.equals(ftype)) 2796 throw misMatchedTypes("target and fallback types", ttype, ftype); 2797 if (gtype.returnType() != boolean.class) 2798 throw newIllegalArgumentException("guard type is not a predicate "+gtype); 2799 List<Class<?>> targs = ttype.parameterList(); 2800 List<Class<?>> gargs = gtype.parameterList(); 2801 if (!targs.equals(gargs)) { 2802 int gpc = gargs.size(), tpc = targs.size(); 2803 if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs)) 2804 throw misMatchedTypes("target and test types", ttype, gtype); 2805 test = dropArguments(test, gpc, targs.subList(gpc, tpc)); 2806 gtype = test.type(); 2807 } 2808 2809 return new Transformers.GuardWithTest(test, target, fallback); 2810 } 2811 misMatchedTypes(String what, MethodType t1, MethodType t2)2812 static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) { 2813 return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2); 2814 } 2815 2816 /** 2817 * Makes a method handle which adapts a target method handle, 2818 * by running it inside an exception handler. 2819 * If the target returns normally, the adapter returns that value. 2820 * If an exception matching the specified type is thrown, the fallback 2821 * handle is called instead on the exception, plus the original arguments. 2822 * <p> 2823 * The target and handler must have the same corresponding 2824 * argument and return types, except that handler may omit trailing arguments 2825 * (similarly to the predicate in {@link #guardWithTest guardWithTest}). 2826 * Also, the handler must have an extra leading parameter of {@code exType} or a supertype. 2827 * <p> Here is pseudocode for the resulting adapter: 2828 * <blockquote><pre>{@code 2829 * T target(A..., B...); 2830 * T handler(ExType, A...); 2831 * T adapter(A... a, B... b) { 2832 * try { 2833 * return target(a..., b...); 2834 * } catch (ExType ex) { 2835 * return handler(ex, a...); 2836 * } 2837 * } 2838 * }</pre></blockquote> 2839 * Note that the saved arguments ({@code a...} in the pseudocode) cannot 2840 * be modified by execution of the target, and so are passed unchanged 2841 * from the caller to the handler, if the handler is invoked. 2842 * <p> 2843 * The target and handler must return the same type, even if the handler 2844 * always throws. (This might happen, for instance, because the handler 2845 * is simulating a {@code finally} clause). 2846 * To create such a throwing handler, compose the handler creation logic 2847 * with {@link #throwException throwException}, 2848 * in order to create a method handle of the correct return type. 2849 * @param target method handle to call 2850 * @param exType the type of exception which the handler will catch 2851 * @param handler method handle to call if a matching exception is thrown 2852 * @return method handle which incorporates the specified try/catch logic 2853 * @throws NullPointerException if any argument is null 2854 * @throws IllegalArgumentException if {@code handler} does not accept 2855 * the given exception type, or if the method handle types do 2856 * not match in their return types and their 2857 * corresponding parameters 2858 */ 2859 public static catchException(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler)2860 MethodHandle catchException(MethodHandle target, 2861 Class<? extends Throwable> exType, 2862 MethodHandle handler) { 2863 MethodType ttype = target.type(); 2864 MethodType htype = handler.type(); 2865 if (htype.parameterCount() < 1 || 2866 !htype.parameterType(0).isAssignableFrom(exType)) 2867 throw newIllegalArgumentException("handler does not accept exception type "+exType); 2868 if (htype.returnType() != ttype.returnType()) 2869 throw misMatchedTypes("target and handler return types", ttype, htype); 2870 List<Class<?>> targs = ttype.parameterList(); 2871 List<Class<?>> hargs = htype.parameterList(); 2872 hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler 2873 if (!targs.equals(hargs)) { 2874 int hpc = hargs.size(), tpc = targs.size(); 2875 if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs)) 2876 throw misMatchedTypes("target and handler types", ttype, htype); 2877 } 2878 2879 return new Transformers.CatchException(target, handler, exType); 2880 } 2881 2882 /** 2883 * Produces a method handle which will throw exceptions of the given {@code exType}. 2884 * The method handle will accept a single argument of {@code exType}, 2885 * and immediately throw it as an exception. 2886 * The method type will nominally specify a return of {@code returnType}. 2887 * The return type may be anything convenient: It doesn't matter to the 2888 * method handle's behavior, since it will never return normally. 2889 * @param returnType the return type of the desired method handle 2890 * @param exType the parameter type of the desired method handle 2891 * @return method handle which can throw the given exceptions 2892 * @throws NullPointerException if either argument is null 2893 */ 2894 public static throwException(Class<?> returnType, Class<? extends Throwable> exType)2895 MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) { 2896 if (!Throwable.class.isAssignableFrom(exType)) 2897 throw new ClassCastException(exType.getName()); 2898 2899 return new Transformers.AlwaysThrow(returnType, exType); 2900 } 2901 } 2902