MethodHandles.java 165.4 KB
Newer Older
1
/*
2
 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3 4 5 6
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * 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 12 13 14 15 16 17 18 19 20
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
21 22 23
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
24 25
 */

26
package java.lang.invoke;
27

28
import java.lang.reflect.*;
29
import java.util.BitSet;
30
import java.util.List;
31
import java.util.Arrays;
32

33 34 35 36
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyAccess;
import sun.invoke.util.Wrapper;
import sun.reflect.CallerSensitive;
37
import sun.reflect.Reflection;
38
import sun.reflect.misc.ReflectUtil;
39
import sun.security.util.SecurityConstants;
40 41
import java.lang.invoke.LambdaForm.BasicType;
import static java.lang.invoke.LambdaForm.BasicType.*;
42
import static java.lang.invoke.MethodHandleStatics.*;
43
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
44
import static java.lang.invoke.MethodHandleNatives.Constants.*;
45

46
import java.util.concurrent.ConcurrentHashMap;
47

48
/**
49 50
 * This class consists exclusively of static methods that operate on or return
 * method handles. They fall into several categories:
51
 * <ul>
52 53 54
 * <li>Lookup methods which help create method handles for methods and fields.
 * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
 * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
55
 * </ul>
56 57
 * <p>
 * @author John Rose, JSR 292 EG
R
rfield 已提交
58
 * @since 1.7
59 60 61 62 63
 */
public class MethodHandles {

    private MethodHandles() { }  // do not instantiate

64
    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
65 66 67 68 69
    static { MethodHandleImpl.initStatics(); }
    // See IMPL_LOOKUP below.

    //// Method handle creation from ordinary methods.

70
    /**
71 72 73 74 75 76 77
     * Returns a {@link Lookup lookup object} with
     * full capabilities to emulate all supported bytecode behaviors of the caller.
     * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller.
     * Factory methods on the lookup object can create
     * <a href="MethodHandleInfo.html#directmh">direct method handles</a>
     * for any member that the caller has access to via bytecodes,
     * including protected and private fields and methods.
78 79
     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
     * Do not store it in place where untrusted code can access it.
80 81 82 83 84 85 86 87 88 89
     * <p>
     * This method is caller sensitive, which means that it may return different
     * values to different callers.
     * <p>
     * For any given caller class {@code C}, the lookup object returned by this call
     * has equivalent capabilities to any lookup object
     * supplied by the JVM to the bootstrap method of an
     * <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
     * executing in the same caller class {@code C}.
     * @return a lookup object for the caller of this method, with private access
90
     */
91
    @CallerSensitive
92
    public static Lookup lookup() {
93
        return new Lookup(Reflection.getCallerClass());
94 95
    }

96
    /**
97
     * Returns a {@link Lookup lookup object} which is trusted minimally.
98 99
     * It can only be used to create method handles to
     * publicly accessible fields and methods.
100 101 102
     * <p>
     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
     * of this lookup object will be {@link java.lang.Object}.
103 104 105
     *
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
106
     * The lookup class can be changed to any other class {@code C} using an expression of the form
107
     * {@link Lookup#in publicLookup().in(C.class)}.
108 109
     * Since all classes have equal access to public names,
     * such a change would confer no new access rights.
110 111 112 113
     * A public lookup object is always subject to
     * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
     * Also, it cannot access
     * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>.
114
     * @return a lookup object which is trusted minimally
115 116 117 118 119
     */
    public static Lookup publicLookup() {
        return Lookup.PUBLIC_LOOKUP;
    }

R
rfield 已提交
120
    /**
121 122
     * Performs an unchecked "crack" of a
     * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
R
rfield 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
     * The result is as if the user had obtained a lookup object capable enough
     * to crack the target method handle, called
     * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
     * on the target to obtain its symbolic reference, and then called
     * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
     * to resolve the symbolic reference to a member.
     * <p>
     * If there is a security manager, its {@code checkPermission} method
     * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
     * @param <T> the desired type of the result, either {@link Member} or a subtype
     * @param target a direct method handle to crack into symbolic reference components
     * @param expected a class object representing the desired result type {@code T}
     * @return a reference to the method, constructor, or field object
     * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
     * @exception NullPointerException if either argument is {@code null}
     * @exception IllegalArgumentException if the target is not a direct method handle
     * @exception ClassCastException if the member is not of the expected type
     * @since 1.8
     */
    public static <T extends Member> T
    reflectAs(Class<T> expected, MethodHandle target) {
        SecurityManager smgr = System.getSecurityManager();
        if (smgr != null)  smgr.checkPermission(ACCESS_PERMISSION);
        Lookup lookup = Lookup.IMPL_LOOKUP;  // use maximally privileged lookup
        return lookup.revealDirect(target).reflectAs(expected, lookup);
    }
    // Copied from AccessibleObject, as used by Method.setAccessible, etc.:
    static final private java.security.Permission ACCESS_PERMISSION =
        new ReflectPermission("suppressAccessChecks");

153
    /**
154 155 156
     * A <em>lookup object</em> is a factory for creating method handles,
     * when the creation requires access checking.
     * Method handles do not perform
157
     * access checks when they are called, but rather when they are created.
158 159
     * Therefore, method handle access
     * restrictions must be enforced when a method handle is created.
160
     * The caller class against which those restrictions are enforced
161
     * is known as the {@linkplain #lookupClass lookup class}.
162 163 164 165 166 167 168 169 170
     * <p>
     * A lookup class which needs to create method handles will call
     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
     * When the {@code Lookup} factory object is created, the identity of the lookup class is
     * determined, and securely stored in the {@code Lookup} object.
     * The lookup class (or its delegates) may then use factory methods
     * on the {@code Lookup} object to create method handles for access-checked members.
     * This includes all methods, constructors, and fields which are allowed to the lookup class,
     * even private ones.
171 172
     *
     * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
173 174
     * The factory methods on a {@code Lookup} object correspond to all major
     * use cases for methods, constructors, and fields.
175 176 177
     * Each method handle created by a factory method is the functional
     * equivalent of a particular <em>bytecode behavior</em>.
     * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.)
178 179 180
     * Here is a summary of the correspondence between these factory methods and
     * the behavior the resulting method handles:
     * <table border=1 cellpadding=5 summary="lookup method behaviors">
181 182 183 184 185
     * <tr>
     *     <th><a name="equiv"></a>lookup expression</th>
     *     <th>member</th>
     *     <th>bytecode behavior</th>
     * </tr>
186
     * <tr>
187 188
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
     *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
189 190
     * </tr>
     * <tr>
191 192
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
193 194
     * </tr>
     * <tr>
195 196
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
     *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
197 198
     * </tr>
     * <tr>
199 200
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
201 202
     * </tr>
     * <tr>
203 204
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
     *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
205 206
     * </tr>
     * <tr>
207 208
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
     *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
209 210
     * </tr>
     * <tr>
211 212
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
     *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
213 214
     * </tr>
     * <tr>
215 216
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
     *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
217 218
     * </tr>
     * <tr>
219 220
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
221 222
     * </tr>
     * <tr>
223 224
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
225 226
     * </tr>
     * <tr>
227 228
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
229 230
     * </tr>
     * <tr>
231 232
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
     *     <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
233 234
     * </tr>
     * <tr>
235 236
     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
237 238
     * </tr>
     * </table>
239
     *
240 241
     * Here, the type {@code C} is the class or interface being searched for a member,
     * documented as a parameter named {@code refc} in the lookup methods.
242
     * The method type {@code MT} is composed from the return type {@code T}
243
     * and the sequence of argument types {@code A*}.
244 245
     * The constructor also has a sequence of argument types {@code A*} and
     * is deemed to return the newly-created object of type {@code C}.
246 247 248
     * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
     * The formal parameter {@code this} stands for the self-reference of type {@code C};
     * if it is present, it is always the leading argument to the method handle invocation.
249 250
     * (In the case of some {@code protected} members, {@code this} may be
     * restricted in type to the lookup class; see below.)
251 252 253 254 255 256 257
     * The name {@code arg} stands for all the other method handle arguments.
     * In the code examples for the Core Reflection API, the name {@code thisOrNull}
     * stands for a null reference if the accessed method or field is static,
     * and {@code this} otherwise.
     * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
     * for reflective objects corresponding to the given members.
     * <p>
258 259 260
     * In cases where the given member is of variable arity (i.e., a method or constructor)
     * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}.
     * In all other cases, the returned method handle will be of fixed arity.
261 262
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
263
     * The equivalence between looked-up method handles and underlying
264 265 266
     * class members and bytecode behaviors
     * can break down in a few ways:
     * <ul style="font-size:smaller;">
267 268 269 270 271 272 273
     * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
     * the lookup can still succeed, even when there is no equivalent
     * Java expression or bytecoded constant.
     * <li>Likewise, if {@code T} or {@code MT}
     * is not symbolically accessible from the lookup class's loader,
     * the lookup can still succeed.
     * For example, lookups for {@code MethodHandle.invokeExact} and
274
     * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
275
     * <li>If there is a security manager installed, it can forbid the lookup
276 277 278
     * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>).
     * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle}
     * constant is not subject to security manager checks.
279 280 281 282
     * <li>If the looked-up method has a
     * <a href="MethodHandle.html#maxarity">very large arity</a>,
     * the method handle creation may fail, due to the method handle
     * type having too many parameters.
283 284
     * </ul>
     *
285
     * <h1><a name="access"></a>Access checking</h1>
286 287 288
     * Access checks are applied in the factory methods of {@code Lookup},
     * when a method handle is created.
     * This is a key difference from the Core Reflection API, since
289
     * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
290 291 292 293 294 295
     * performs access checking against every caller, on every call.
     * <p>
     * All access checks start from a {@code Lookup} object, which
     * compares its recorded lookup class against all requests to
     * create method handles.
     * A single {@code Lookup} object can be used to create any number
296 297 298
     * of access-checked method handles, all checked against a single
     * lookup class.
     * <p>
299 300 301 302 303 304 305
     * A {@code Lookup} object can be shared with other trusted code,
     * such as a metaobject protocol.
     * A shared {@code Lookup} object delegates the capability
     * to create method handles on private members of the lookup class.
     * Even if privileged code uses the {@code Lookup} object,
     * the access checking is confined to the privileges of the
     * original lookup class.
306
     * <p>
307
     * A lookup can fail, because
308 309
     * the containing class is not accessible to the lookup class, or
     * because the desired class member is missing, or because the
310 311
     * desired class member is not accessible to the lookup class, or
     * because the lookup object is not trusted enough to access the member.
312 313 314 315 316 317 318 319
     * In any of these cases, a {@code ReflectiveOperationException} will be
     * thrown from the attempted lookup.  The exact class will be one of
     * the following:
     * <ul>
     * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
     * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
     * <li>IllegalAccessException &mdash; if the member exists but an access check fails
     * </ul>
320
     * <p>
321
     * In general, the conditions under which a method handle may be
322 323
     * looked up for a method {@code M} are no more restrictive than the conditions
     * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
324 325 326
     * Where the JVM would raise exceptions like {@code NoSuchMethodError},
     * a method handle lookup will generally raise a corresponding
     * checked exception, such as {@code NoSuchMethodException}.
327
     * And the effect of invoking the method handle resulting from the lookup
328 329
     * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
     * to executing the compiled, verified, and resolved call to {@code M}.
330
     * The same point is true of fields and constructors.
331 332 333 334 335 336 337 338
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
     * Access checks only apply to named and reflected methods,
     * constructors, and fields.
     * Other method handle creation methods, such as
     * {@link MethodHandle#asType MethodHandle.asType},
     * do not require any access checks, and are used
     * independently of any {@code Lookup} object.
339
     * <p>
340 341 342 343 344 345 346 347 348 349 350 351
     * If the desired member is {@code protected}, the usual JVM rules apply,
     * including the requirement that the lookup class must be either be in the
     * same package as the desired member, or must inherit that member.
     * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.)
     * In addition, if the desired member is a non-static field or method
     * in a different package, the resulting method handle may only be applied
     * to objects of the lookup class or one of its subclasses.
     * This requirement is enforced by narrowing the type of the leading
     * {@code this} parameter from {@code C}
     * (which will necessarily be a superclass of the lookup class)
     * to the lookup class itself.
     * <p>
352 353 354 355 356 357
     * The JVM imposes a similar requirement on {@code invokespecial} instruction,
     * that the receiver argument must match both the resolved method <em>and</em>
     * the current class.  Again, this requirement is enforced by narrowing the
     * type of the leading parameter to the resulting method handle.
     * (See the Java Virtual Machine Specification, section 4.10.1.9.)
     * <p>
358 359 360 361 362 363
     * The JVM represents constructors and static initializer blocks as internal methods
     * with special names ({@code "<init>"} and {@code "<clinit>"}).
     * The internal syntax of invocation instructions allows them to refer to such internal
     * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
     * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
     * <p>
364
     * In some cases, access between nested classes is obtained by the Java compiler by creating
365 366
     * an wrapper method to access a private method of another class
     * in the same top-level declaration.
367
     * For example, a nested class {@code C.D}
368
     * can access private members within other related classes such as
369 370 371 372 373 374 375
     * {@code C}, {@code C.D.E}, or {@code C.B},
     * but the Java compiler may need to generate wrapper methods in
     * those related classes.  In such cases, a {@code Lookup} object on
     * {@code C.E} would be unable to those private members.
     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
     * which can transform a lookup on {@code C.E} into one on any of those other
     * classes, without special elevation of privilege.
376
     * <p>
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
     * The accesses permitted to a given lookup object may be limited,
     * according to its set of {@link #lookupModes lookupModes},
     * to a subset of members normally accessible to the lookup class.
     * For example, the {@link MethodHandles#publicLookup publicLookup}
     * method produces a lookup object which is only allowed to access
     * public members in public classes.
     * The caller sensitive method {@link MethodHandles#lookup lookup}
     * produces a lookup object with full capabilities relative to
     * its caller class, to emulate all supported bytecode behaviors.
     * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
     * with fewer access modes than the original lookup object.
     *
     * <p style="font-size:smaller;">
     * <a name="privacc"></a>
     * <em>Discussion of private access:</em>
     * We say that a lookup has <em>private access</em>
     * if its {@linkplain #lookupModes lookup modes}
     * include the possibility of accessing {@code private} members.
     * As documented in the relevant methods elsewhere,
     * only lookups with private access possess the following capabilities:
     * <ul style="font-size:smaller;">
     * <li>access private fields, methods, and constructors of the lookup class
     * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
     *     such as {@code Class.forName}
     * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
     * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
     *     for classes accessible to the lookup class
     * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
     *     within the same package member
     * </ul>
     * <p style="font-size:smaller;">
     * Each of these permissions is a consequence of the fact that a lookup object
     * with private access can be securely traced back to an originating class,
     * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
     * can be reliably determined and emulated by method handles.
     *
     * <h1><a name="secmgr"></a>Security manager interactions</h1>
414 415 416 417 418 419 420 421 422 423 424 425 426 427
     * Although bytecode instructions can only refer to classes in
     * a related class loader, this API can search for methods in any
     * class, as long as a reference to its {@code Class} object is
     * available.  Such cross-loader references are also possible with the
     * Core Reflection API, and are impossible to bytecode instructions
     * such as {@code invokestatic} or {@code getfield}.
     * There is a {@linkplain java.lang.SecurityManager security manager API}
     * to allow applications to check such cross-loader references.
     * These checks apply to both the {@code MethodHandles.Lookup} API
     * and the Core Reflection API
     * (as found on {@link java.lang.Class Class}).
     * <p>
     * If a security manager is present, member lookups are subject to
     * additional checks.
428
     * From one to three calls are made to the security manager.
429 430 431
     * Any of these calls can refuse access by throwing a
     * {@link java.lang.SecurityException SecurityException}.
     * Define {@code smgr} as the security manager,
432
     * {@code lookc} as the lookup class of the current lookup object,
433 434 435
     * {@code refc} as the containing class in which the member
     * is being sought, and {@code defc} as the class in which the
     * member is actually defined.
436 437
     * The value {@code lookc} is defined as <em>not present</em>
     * if the current lookup object does not have
438
     * <a href="MethodHandles.Lookup.html#privacc">private access</a>.
439 440
     * The calls are made according to the following rules:
     * <ul>
441 442
     * <li><b>Step 1:</b>
     *     If {@code lookc} is not present, or if its class loader is not
443 444 445 446
     *     the same as or an ancestor of the class loader of {@code refc},
     *     then {@link SecurityManager#checkPackageAccess
     *     smgr.checkPackageAccess(refcPkg)} is called,
     *     where {@code refcPkg} is the package of {@code refc}.
447 448
     * <li><b>Step 2:</b>
     *     If the retrieved member is not public and
449 450 451
     *     {@code lookc} is not present, then
     *     {@link SecurityManager#checkPermission smgr.checkPermission}
     *     with {@code RuntimePermission("accessDeclaredMembers")} is called.
452 453
     * <li><b>Step 3:</b>
     *     If the retrieved member is not public,
454
     *     and if {@code lookc} is not present,
455
     *     and if {@code defc} and {@code refc} are different,
456 457 458 459
     *     then {@link SecurityManager#checkPackageAccess
     *     smgr.checkPackageAccess(defcPkg)} is called,
     *     where {@code defcPkg} is the package of {@code defc}.
     * </ul>
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
     * Security checks are performed after other access checks have passed.
     * Therefore, the above rules presuppose a member that is public,
     * or else that is being accessed from a lookup class that has
     * rights to access the member.
     *
     * <h1><a name="callsens"></a>Caller sensitive methods</h1>
     * A small number of Java methods have a special property called caller sensitivity.
     * A <em>caller-sensitive</em> method can behave differently depending on the
     * identity of its immediate caller.
     * <p>
     * If a method handle for a caller-sensitive method is requested,
     * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply,
     * but they take account of the lookup class in a special way.
     * The resulting method handle behaves as if it were called
     * from an instruction contained in the lookup class,
     * so that the caller-sensitive method detects the lookup class.
     * (By contrast, the invoker of the method handle is disregarded.)
     * Thus, in the case of caller-sensitive methods,
     * different lookup classes may give rise to
     * differently behaving method handles.
     * <p>
     * In cases where the lookup object is
     * {@link MethodHandles#publicLookup() publicLookup()},
     * or some other lookup object without
484
     * <a href="MethodHandles.Lookup.html#privacc">private access</a>,
485 486 487 488
     * the lookup class is disregarded.
     * In such cases, no caller-sensitive method handle can be created,
     * access is forbidden, and the lookup fails with an
     * {@code IllegalAccessException}.
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
     * For example, the caller-sensitive method
     * {@link java.lang.Class#forName(String) Class.forName(x)}
     * can return varying classes or throw varying exceptions,
     * depending on the class loader of the class that calls it.
     * A public lookup of {@code Class.forName} will fail, because
     * there is no reasonable way to determine its bytecode behavior.
     * <p style="font-size:smaller;">
     * If an application caches method handles for broad sharing,
     * it should use {@code publicLookup()} to create them.
     * If there is a lookup of {@code Class.forName}, it will fail,
     * and the application must take appropriate action in that case.
     * It may be that a later lookup, perhaps during the invocation of a
     * bootstrap method, can incorporate the specific identity
     * of the caller, making the method accessible.
     * <p style="font-size:smaller;">
     * The function {@code MethodHandles.lookup} is caller sensitive
     * so that there can be a secure foundation for lookups.
     * Nearly all other methods in the JSR 292 API rely on lookup
     * objects to check access requests.
510 511 512
     */
    public static final
    class Lookup {
513
        /** The class on behalf of whom the lookup is being performed. */
514 515
        private final Class<?> lookupClass;

516
        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
517 518
        private final int allowedModes;

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
        /** A single-bit mask representing {@code public} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x01}, happens to be the same as the value of the
         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
         */
        public static final int PUBLIC = Modifier.PUBLIC;

        /** A single-bit mask representing {@code private} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x02}, happens to be the same as the value of the
         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
         */
        public static final int PRIVATE = Modifier.PRIVATE;

        /** A single-bit mask representing {@code protected} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x04}, happens to be the same as the value of the
         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
         */
        public static final int PROTECTED = Modifier.PROTECTED;

        /** A single-bit mask representing {@code package} access (default access),
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value is {@code 0x08}, which does not correspond meaningfully to
         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
         */
        public static final int PACKAGE = Modifier.STATIC;

        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
        private static final int TRUSTED   = -1;
549 550 551 552 553 554

        private static int fixmods(int mods) {
            mods &= (ALL_MODES - PACKAGE);
            return (mods != 0) ? mods : PACKAGE;
        }

555
        /** Tells which class is performing the lookup.  It is this class against
556 557
         *  which checks are performed for visibility and access permissions.
         *  <p>
558 559
         *  The class implies a maximum level of access permission,
         *  but the permissions may be additionally limited by the bitmask
560
         *  {@link #lookupModes lookupModes}, which controls whether non-public members
561
         *  can be accessed.
562
         *  @return the lookup class, on behalf of which this lookup object finds members
563 564 565 566 567
         */
        public Class<?> lookupClass() {
            return lookupClass;
        }

568 569 570 571 572
        // This is just for calling out to MethodHandleImpl.
        private Class<?> lookupClassOrNull() {
            return (allowedModes == TRUSTED) ? null : lookupClass;
        }

573
        /** Tells which access-protection classes of members this lookup object can produce.
574 575 576 577 578
         *  The result is a bit-mask of the bits
         *  {@linkplain #PUBLIC PUBLIC (0x01)},
         *  {@linkplain #PRIVATE PRIVATE (0x02)},
         *  {@linkplain #PROTECTED PROTECTED (0x04)},
         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
579 580
         *  <p>
         *  A freshly-created lookup object
581
         *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
582 583
         *  has all possible bits set, since the caller class can access all its own members.
         *  A lookup object on a new lookup class
584
         *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
585 586 587 588
         *  may have some mode bits set to zero.
         *  The purpose of this is to restrict access via the new lookup object,
         *  so that it can access only names which can be reached by the original
         *  lookup object, and also by the new lookup class.
589
         *  @return the lookup modes, which limit the kinds of access performed by this lookup object
590
         */
591
        public int lookupModes() {
592 593 594
            return allowedModes & ALL_MODES;
        }

595 596 597 598 599
        /** Embody the current class (the lookupClass) as a lookup class
         * for method handle creation.
         * Must be called by from a method in this package,
         * which in turn is called by a method not in this package.
         */
600
        Lookup(Class<?> lookupClass) {
601
            this(lookupClass, ALL_MODES);
602
            // make sure we haven't accidentally picked up a privileged class:
603
            checkUnprivilegedlookupClass(lookupClass, ALL_MODES);
604 605 606
        }

        private Lookup(Class<?> lookupClass, int allowedModes) {
607
            this.lookupClass = lookupClass;
608
            this.allowedModes = allowedModes;
609 610 611
        }

        /**
612
         * Creates a lookup on the specified new lookup class.
613
         * The resulting object will report the specified
614
         * class as its own {@link #lookupClass lookupClass}.
615 616 617
         * <p>
         * However, the resulting {@code Lookup} object is guaranteed
         * to have no more access capabilities than the original.
618
         * In particular, access capabilities can be lost as follows:<ul>
619 620
         * <li>If the new lookup class differs from the old one,
         * protected members will not be accessible by virtue of inheritance.
621
         * (Protected members may continue to be accessible because of package sharing.)
622 623 624 625
         * <li>If the new lookup class is in a different package
         * than the old one, protected and default (package) members will not be accessible.
         * <li>If the new lookup class is not within the same package member
         * as the old one, private members will not be accessible.
626 627 628
         * <li>If the new lookup class is not accessible to the old lookup class,
         * then no members, not even public members, will be accessible.
         * (In all other cases, public members will continue to be accessible.)
629
         * </ul>
630 631 632 633
         *
         * @param requestedLookupClass the desired lookup class for the new lookup object
         * @return a lookup object which reports the desired lookup class
         * @throws NullPointerException if the argument is null
634
         */
635 636 637 638 639 640 641 642 643 644
        public Lookup in(Class<?> requestedLookupClass) {
            requestedLookupClass.getClass();  // null check
            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
                return new Lookup(requestedLookupClass, ALL_MODES);
            if (requestedLookupClass == this.lookupClass)
                return this;  // keep same capabilities
            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
            if ((newModes & PACKAGE) != 0
                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
                newModes &= ~(PACKAGE|PRIVATE);
645
            }
646
            // Allow nestmate lookups to be created without special privilege:
647 648 649 650
            if ((newModes & PRIVATE) != 0
                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
                newModes &= ~PRIVATE;
            }
651 652
            if ((newModes & PUBLIC) != 0
                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
653 654 655 656
                // The requested class it not accessible from the lookup class.
                // No permissions.
                newModes = 0;
            }
657
            checkUnprivilegedlookupClass(requestedLookupClass, newModes);
658
            return new Lookup(requestedLookupClass, newModes);
659 660
        }

661
        // Make sure outer class is initialized first.
662
        static { IMPL_NAMES.getClass(); }
663

664 665 666 667
        /** Version of lookup which is trusted minimally.
         *  It can only be used to create method handles to
         *  publicly accessible members.
         */
668
        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
669 670

        /** Package-private version of lookup which is trusted. */
671
        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
672

673
        private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
674
            String name = lookupClass.getName();
675
            if (name.startsWith("java.lang.invoke."))
676
                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
677 678 679 680 681 682 683 684 685

            // For caller-sensitive MethodHandles.lookup()
            // disallow lookup more restricted packages
            if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
                if (name.startsWith("java.") ||
                        (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
                    throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
                }
            }
686 687
        }

688
        /**
689
         * Displays the name of the class from which lookups are to be made.
690 691 692
         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
         * If there are restrictions on the access permitted to this lookup,
         * this is indicated by adding a suffix to the class name, consisting
693 694
         * of a slash and a keyword.  The keyword represents the strongest
         * allowed access, and is chosen as follows:
695 696 697 698 699 700 701 702 703 704
         * <ul>
         * <li>If no access is allowed, the suffix is "/noaccess".
         * <li>If only public access is allowed, the suffix is "/public".
         * <li>If only public and package access are allowed, the suffix is "/package".
         * <li>If only public, package, and private access are allowed, the suffix is "/private".
         * </ul>
         * If none of the above cases apply, it is the case that full
         * access (public, package, private, and protected) is allowed.
         * In this case, no suffix is added.
         * This is true only of an object obtained originally from
705 706
         * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
         * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
707
         * always have restricted access, and will display a suffix.
708 709 710 711 712 713 714
         * <p>
         * (It may seem strange that protected access should be
         * stronger than private access.  Viewed independently from
         * package access, protected access is the first to be lost,
         * because it requires a direct subclass relationship between
         * caller and callee.)
         * @see #in
715
         */
716 717
        @Override
        public String toString() {
718 719
            String cname = lookupClass.getName();
            switch (allowedModes) {
720 721
            case 0:  // no privileges
                return cname + "/noaccess";
722
            case PUBLIC:
723
                return cname + "/public";
724 725
            case PUBLIC|PACKAGE:
                return cname + "/package";
726 727
            case ALL_MODES & ~PROTECTED:
                return cname + "/private";
728 729
            case ALL_MODES:
                return cname;
730 731 732 733 734 735
            case TRUSTED:
                return "/trusted";  // internal only; not exported
            default:  // Should not happen, but it's a bitfield...
                cname = cname + "/" + Integer.toHexString(allowedModes);
                assert(false) : cname;
                return cname;
736
            }
737 738 739
        }

        /**
740
         * Produces a method handle for a static method.
741
         * The type of the method handle will be that of the method.
742 743
         * (Since static methods do not take receivers, there is no
         * additional receiver argument inserted into the method handle type,
744
         * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
745
         * The method and all its argument types must be accessible to the lookup object.
746 747 748 749
         * <p>
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set.
750 751 752 753
         * <p>
         * If the returned method handle is invoked, the method's class will
         * be initialized, if it has not already been initialized.
         * <p><b>Example:</b>
754
         * <blockquote><pre>{@code
755 756 757 758 759 760 761
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
  "asList", methodType(List.class, Object[].class));
assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
         * }</pre></blockquote>
762
         * @param refc the class from which the method is accessed
763 764 765
         * @param name the name of the method
         * @param type the type of the method
         * @return the desired method handle
766
         * @throws NoSuchMethodException if the method does not exist
767 768 769 770
         * @throws IllegalAccessException if access checking fails,
         *                                or if the method is not {@code static},
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
771 772
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
773
         * @throws NullPointerException if any argument is null
774 775
         */
        public
776
        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
777
            MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
778
            return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method));
779
        }
780 781

        /**
782
         * Produces a method handle for a virtual method.
783
         * The type of the method handle will be that of the method,
784
         * with the receiver type (usually {@code refc}) prepended.
785
         * The method and all its argument types must be accessible to the lookup object.
786 787 788 789 790 791
         * <p>
         * When called, the handle will treat the first argument as a receiver
         * and dispatch on the receiver's type to determine which method
         * implementation to enter.
         * (The dispatching action is identical with that performed by an
         * {@code invokevirtual} or {@code invokeinterface} instruction.)
792
         * <p>
793 794 795 796 797
         * The first argument will be of type {@code refc} if the lookup
         * class has full privileges to access the member.  Otherwise
         * the member must be {@code protected} and the first argument
         * will be restricted in type to the lookup class.
         * <p>
798 799 800
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set.
801
         * <p>
802
         * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
803 804
         * instructions and method handles produced by {@code findVirtual},
         * if the class is {@code MethodHandle} and the name string is
805
         * {@code invokeExact} or {@code invoke}, the resulting
806
         * method handle is equivalent to one produced by
807
         * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
808
         * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
809 810
         * with the same {@code type} argument.
         *
811
         * <b>Example:</b>
812
         * <blockquote><pre>{@code
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_concat = publicLookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
  "hashCode", methodType(int.class));
MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
  "hashCode", methodType(int.class));
assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
// interface method:
MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
  "subSequence", methodType(CharSequence.class, int.class, int.class));
assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
// constructor "internal method" must be accessed differently:
MethodType MT_newString = methodType(void.class); //()V for new String()
try { assertEquals("impossible", lookup()
        .findVirtual(String.class, "<init>", MT_newString));
 } catch (NoSuchMethodException ex) { } // OK
MethodHandle MH_newString = publicLookup()
  .findConstructor(String.class, MT_newString);
assertEquals("", (String) MH_newString.invokeExact());
         * }</pre></blockquote>
         *
839
         * @param refc the class or interface from which the method is accessed
840 841 842
         * @param name the name of the method
         * @param type the type of the method, with the receiver argument omitted
         * @return the desired method handle
843
         * @throws NoSuchMethodException if the method does not exist
844 845 846 847
         * @throws IllegalAccessException if access checking fails,
         *                                or if the method is {@code static}
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
848 849
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
850
         * @throws NullPointerException if any argument is null
851
         */
852
        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
853 854 855 856 857 858
            if (refc == MethodHandle.class) {
                MethodHandle mh = findVirtualForMH(name, type);
                if (mh != null)  return mh;
            }
            byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
            MemberName method = resolveOrFail(refKind, refc, name, type);
859
            return getDirectMethod(refKind, refc, method, findBoundCallerClass(method));
860
        }
861 862 863 864 865 866
        private MethodHandle findVirtualForMH(String name, MethodType type) {
            // these names require special lookups because of the implicit MethodType argument
            if ("invoke".equals(name))
                return invoker(type);
            if ("invokeExact".equals(name))
                return exactInvoker(type);
867 868
            if ("invokeBasic".equals(name))
                return basicInvoker(type);
R
rfield 已提交
869
            assert(!MemberName.isMethodHandleInvokeName(name));
870
            return null;
871 872 873
        }

        /**
874
         * Produces a method handle which creates an object and initializes it, using
875 876 877
         * the constructor of the specified type.
         * The parameter types of the method handle will be those of the constructor,
         * while the return type will be a reference to the constructor's class.
878
         * The constructor and all its argument types must be accessible to the lookup object.
879
         * <p>
880 881
         * The requested type must have a return type of {@code void}.
         * (This is consistent with the JVM's treatment of constructor type descriptors.)
882 883 884 885
         * <p>
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
886 887 888
         * <p>
         * If the returned method handle is invoked, the constructor's class will
         * be initialized, if it has not already been initialized.
889
         * <p><b>Example:</b>
890
         * <blockquote><pre>{@code
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_newArrayList = publicLookup().findConstructor(
  ArrayList.class, methodType(void.class, Collection.class));
Collection orig = Arrays.asList("x", "y");
Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
assert(orig != copy);
assertEquals(orig, copy);
// a variable-arity constructor:
MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
  ProcessBuilder.class, methodType(void.class, String[].class));
ProcessBuilder pb = (ProcessBuilder)
  MH_newProcessBuilder.invoke("x", "y", "z");
assertEquals("[x, y, z]", pb.command().toString());
         * }</pre></blockquote>
907 908 909
         * @param refc the class or interface from which the method is accessed
         * @param type the type of the method, with the receiver argument omitted, and a void return type
         * @return the desired method handle
910 911
         * @throws NoSuchMethodException if the constructor does not exist
         * @throws IllegalAccessException if access checking fails
912 913
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
914 915
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
916
         * @throws NullPointerException if any argument is null
917
         */
918
        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
919
            String name = "<init>";
920 921
            MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
            return getDirectConstructor(refc, ctor);
922 923 924
        }

        /**
925 926 927 928
         * Produces an early-bound method handle for a virtual method.
         * It will bypass checks for overriding methods on the receiver,
         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
         * instruction from within the explicitly specified {@code specialCaller}.
929
         * The type of the method handle will be that of the method,
930 931
         * with a suitably restricted receiver type prepended.
         * (The receiver type will be {@code specialCaller} or a subtype.)
932
         * The method and all its argument types must be accessible
933
         * to the lookup object.
934
         * <p>
935 936 937 938
         * Before method resolution,
         * if the explicitly specified caller class is not identical with the
         * lookup class, or if this lookup object does not have
         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
939
         * privileges, the access fails.
940 941 942 943
         * <p>
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set.
944
         * <p style="font-size:smaller;">
945 946 947 948 949
         * <em>(Note:  JVM internal methods named {@code "<init>"} are not visible to this API,
         * even though the {@code invokespecial} instruction can refer to them
         * in special circumstances.  Use {@link #findConstructor findConstructor}
         * to access instance initialization methods in a safe manner.)</em>
         * <p><b>Example:</b>
950
         * <blockquote><pre>{@code
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
static class Listie extends ArrayList {
  public String toString() { return "[wee Listie]"; }
  static Lookup lookup() { return MethodHandles.lookup(); }
}
...
// no access to constructor via invokeSpecial:
MethodHandle MH_newListie = Listie.lookup()
  .findConstructor(Listie.class, methodType(void.class));
Listie l = (Listie) MH_newListie.invokeExact();
try { assertEquals("impossible", Listie.lookup().findSpecial(
        Listie.class, "<init>", methodType(void.class), Listie.class));
 } catch (NoSuchMethodException ex) { } // OK
// access to super and self methods via invokeSpecial:
MethodHandle MH_super = Listie.lookup().findSpecial(
  ArrayList.class, "toString" , methodType(String.class), Listie.class);
MethodHandle MH_this = Listie.lookup().findSpecial(
  Listie.class, "toString" , methodType(String.class), Listie.class);
MethodHandle MH_duper = Listie.lookup().findSpecial(
  Object.class, "toString" , methodType(String.class), Listie.class);
assertEquals("[]", (String) MH_super.invokeExact(l));
assertEquals(""+l, (String) MH_this.invokeExact(l));
assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
try { assertEquals("inaccessible", Listie.lookup().findSpecial(
        String.class, "toString", methodType(String.class), Listie.class));
 } catch (IllegalAccessException ex) { } // OK
Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
         * }</pre></blockquote>
         *
983 984
         * @param refc the class or interface from which the method is accessed
         * @param name the name of the method (which must not be "&lt;init&gt;")
985 986 987
         * @param type the type of the method, with the receiver argument omitted
         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
         * @return the desired method handle
988 989
         * @throws NoSuchMethodException if the method does not exist
         * @throws IllegalAccessException if access checking fails
990 991
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
992 993
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
994
         * @throws NullPointerException if any argument is null
995
         */
996
        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
997
                                        Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
998
            checkSpecialCaller(specialCaller);
999 1000
            Lookup specialLookup = this.in(specialCaller);
            MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
1001
            return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
1002
        }
1003 1004

        /**
1005
         * Produces a method handle giving read access to a non-static field.
1006 1007
         * The type of the method handle will have a return type of the field's
         * value type.
1008
         * The method handle's single argument will be the instance containing
1009 1010
         * the field.
         * Access checking is performed immediately on behalf of the lookup class.
1011
         * @param refc the class or interface from which the method is accessed
1012 1013 1014
         * @param name the field's name
         * @param type the field's type
         * @return a method handle which can load values from the field
1015 1016
         * @throws NoSuchFieldException if the field does not exist
         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1017 1018
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1019
         * @throws NullPointerException if any argument is null
1020
         */
1021
        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1022 1023
            MemberName field = resolveOrFail(REF_getField, refc, name, type);
            return getDirectField(REF_getField, refc, field);
1024
        }
1025 1026

        /**
1027
         * Produces a method handle giving write access to a non-static field.
1028
         * The type of the method handle will have a void return type.
1029
         * The method handle will take two arguments, the instance containing
1030
         * the field, and the value to be stored.
1031 1032
         * The second argument will be of the field's value type.
         * Access checking is performed immediately on behalf of the lookup class.
1033
         * @param refc the class or interface from which the method is accessed
1034 1035 1036
         * @param name the field's name
         * @param type the field's type
         * @return a method handle which can store values into the field
1037 1038
         * @throws NoSuchFieldException if the field does not exist
         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1039 1040
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1041
         * @throws NullPointerException if any argument is null
1042
         */
1043
        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1044 1045
            MemberName field = resolveOrFail(REF_putField, refc, name, type);
            return getDirectField(REF_putField, refc, field);
1046
        }
1047 1048

        /**
1049
         * Produces a method handle giving read access to a static field.
1050 1051 1052 1053
         * The type of the method handle will have a return type of the field's
         * value type.
         * The method handle will take no arguments.
         * Access checking is performed immediately on behalf of the lookup class.
1054 1055 1056
         * <p>
         * If the returned method handle is invoked, the field's class will
         * be initialized, if it has not already been initialized.
1057
         * @param refc the class or interface from which the method is accessed
1058 1059 1060
         * @param name the field's name
         * @param type the field's type
         * @return a method handle which can load values from the field
1061 1062
         * @throws NoSuchFieldException if the field does not exist
         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
1063 1064
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1065
         * @throws NullPointerException if any argument is null
1066
         */
1067
        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1068 1069
            MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
            return getDirectField(REF_getStatic, refc, field);
1070
        }
1071 1072

        /**
1073
         * Produces a method handle giving write access to a static field.
1074 1075 1076
         * The type of the method handle will have a void return type.
         * The method handle will take a single
         * argument, of the field's value type, the value to be stored.
1077
         * Access checking is performed immediately on behalf of the lookup class.
1078 1079 1080
         * <p>
         * If the returned method handle is invoked, the field's class will
         * be initialized, if it has not already been initialized.
1081
         * @param refc the class or interface from which the method is accessed
1082 1083
         * @param name the field's name
         * @param type the field's type
1084
         * @return a method handle which can store values into the field
1085 1086
         * @throws NoSuchFieldException if the field does not exist
         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
1087 1088
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1089
         * @throws NullPointerException if any argument is null
1090
         */
1091
        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1092 1093
            MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
            return getDirectField(REF_putStatic, refc, field);
1094
        }
1095 1096

        /**
1097
         * Produces an early-bound method handle for a non-static method.
1098 1099
         * The receiver must have a supertype {@code defc} in which a method
         * of the given name and type is accessible to the lookup class.
1100
         * The method and all its argument types must be accessible to the lookup object.
1101 1102 1103 1104 1105
         * The type of the method handle will be that of the method,
         * without any insertion of an additional receiver parameter.
         * The given receiver will be bound into the method handle,
         * so that every call to the method handle will invoke the
         * requested method on the given receiver.
1106
         * <p>
1107 1108 1109 1110 1111 1112 1113 1114
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set
         * <em>and</em> the trailing array argument is not the only argument.
         * (If the trailing array argument is the only argument,
         * the given receiver value will be bound to it.)
         * <p>
         * This is equivalent to the following code:
1115
         * <blockquote><pre>{@code
1116 1117 1118
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
1119 1120
MethodHandle mh0 = lookup().findVirtual(defc, name, type);
MethodHandle mh1 = mh0.bindTo(receiver);
1121
MethodType mt1 = mh1.type();
1122
if (mh0.isVarargsCollector())
1123 1124
  mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
return mh1;
1125
         * }</pre></blockquote>
1126 1127 1128
         * where {@code defc} is either {@code receiver.getClass()} or a super
         * type of that class, in which the requested method is accessible
         * to the lookup class.
1129
         * (Note that {@code bindTo} does not preserve variable arity.)
1130 1131 1132 1133
         * @param receiver the object from which the method is accessed
         * @param name the name of the method
         * @param type the type of the method, with the receiver argument omitted
         * @return the desired method handle
1134 1135
         * @throws NoSuchMethodException if the method does not exist
         * @throws IllegalAccessException if access checking fails
1136 1137
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
1138 1139
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1140
         * @throws NullPointerException if any argument is null
1141 1142
         * @see MethodHandle#bindTo
         * @see #findVirtual
1143
         */
1144
        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1145
            Class<? extends Object> refc = receiver.getClass(); // may get NPE
1146
            MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
1147
            MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
1148
            return mh.bindArgumentL(0, receiver).setVarargs(method);
1149 1150 1151
        }

        /**
1152 1153
         * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
         * to <i>m</i>, if the lookup class has permission.
1154 1155 1156 1157 1158 1159 1160 1161
         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
         * If <i>m</i> is virtual, overriding is respected on every call.
         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
         * The type of the method handle will be that of the method,
         * with the receiver type prepended (but only if it is non-static).
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class.
         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
1162 1163 1164 1165
         * <p>
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set.
1166 1167 1168 1169
         * <p>
         * If <i>m</i> is static, and
         * if the returned method handle is invoked, the method's class will
         * be initialized, if it has not already been initialized.
1170 1171
         * @param m the reflected method
         * @return a method handle which can invoke the reflected method
1172
         * @throws IllegalAccessException if access checking fails
1173 1174
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
1175
         * @throws NullPointerException if the argument is null
1176
         */
1177
        public MethodHandle unreflect(Method m) throws IllegalAccessException {
R
rfield 已提交
1178 1179 1180 1181
            if (m.getDeclaringClass() == MethodHandle.class) {
                MethodHandle mh = unreflectForMH(m);
                if (mh != null)  return mh;
            }
1182
            MemberName method = new MemberName(m);
1183 1184 1185
            byte refKind = method.getReferenceKind();
            if (refKind == REF_invokeSpecial)
                refKind = REF_invokeVirtual;
1186
            assert(method.isMethod());
1187
            Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
1188
            return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method));
1189
        }
R
rfield 已提交
1190 1191 1192 1193 1194 1195
        private MethodHandle unreflectForMH(Method m) {
            // these names require special lookups because they throw UnsupportedOperationException
            if (MemberName.isMethodHandleInvokeName(m.getName()))
                return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
            return null;
        }
1196 1197

        /**
1198
         * Produces a method handle for a reflected method.
1199
         * It will bypass checks for overriding methods on the receiver,
1200 1201
         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
         * instruction from within the explicitly specified {@code specialCaller}.
1202
         * The type of the method handle will be that of the method,
1203 1204
         * with a suitably restricted receiver type prepended.
         * (The receiver type will be {@code specialCaller} or a subtype.)
1205 1206 1207
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class,
         * as if {@code invokespecial} instruction were being linked.
1208
         * <p>
1209 1210 1211 1212 1213 1214
         * Before method resolution,
         * if the explicitly specified caller class is not identical with the
         * lookup class, or if this lookup object does not have
         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
         * privileges, the access fails.
         * <p>
1215 1216 1217
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the method's variable arity modifier bit ({@code 0x0080}) is set.
1218
         * @param m the reflected method
1219
         * @param specialCaller the class nominally calling the method
1220
         * @return a method handle which can invoke the reflected method
1221
         * @throws IllegalAccessException if access checking fails
1222 1223
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
1224
         * @throws NullPointerException if any argument is null
1225
         */
1226
        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
1227
            checkSpecialCaller(specialCaller);
1228 1229
            Lookup specialLookup = this.in(specialCaller);
            MemberName method = new MemberName(m, true);
1230 1231
            assert(method.isMethod());
            // ignore m.isAccessible:  this is a new kind of access
1232
            return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method));
1233 1234 1235
        }

        /**
1236
         * Produces a method handle for a reflected constructor.
1237 1238
         * The type of the method handle will be that of the constructor,
         * with the return type changed to the declaring class.
1239 1240 1241 1242 1243
         * The method handle will perform a {@code newInstance} operation,
         * creating a new instance of the constructor's class on the
         * arguments passed to the method handle.
         * <p>
         * If the constructor's {@code accessible} flag is not set,
1244
         * access checking is performed immediately on behalf of the lookup class.
1245 1246 1247 1248
         * <p>
         * The returned method handle will have
         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
1249 1250 1251
         * <p>
         * If the returned method handle is invoked, the constructor's class will
         * be initialized, if it has not already been initialized.
1252
         * @param c the reflected constructor
1253
         * @return a method handle which can invoke the reflected constructor
1254
         * @throws IllegalAccessException if access checking fails
1255 1256
         *                                or if the method's variable arity modifier bit
         *                                is set and {@code asVarargsCollector} fails
1257
         * @throws NullPointerException if the argument is null
1258
         */
1259
        public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
1260 1261
            MemberName ctor = new MemberName(c);
            assert(ctor.isConstructor());
1262
            Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
1263
            return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
1264 1265 1266
        }

        /**
1267
         * Produces a method handle giving read access to a reflected field.
1268
         * The type of the method handle will have a return type of the field's
1269 1270 1271 1272
         * value type.
         * If the field is static, the method handle will take no arguments.
         * Otherwise, its single argument will be the instance containing
         * the field.
1273
         * If the field's {@code accessible} flag is not set,
1274
         * access checking is performed immediately on behalf of the lookup class.
1275 1276 1277 1278
         * <p>
         * If the field is static, and
         * if the returned method handle is invoked, the field's class will
         * be initialized, if it has not already been initialized.
1279 1280
         * @param f the reflected field
         * @return a method handle which can load values from the reflected field
1281 1282
         * @throws IllegalAccessException if access checking fails
         * @throws NullPointerException if the argument is null
1283
         */
1284
        public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
1285 1286 1287 1288 1289 1290 1291 1292
            return unreflectField(f, false);
        }
        private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
            MemberName field = new MemberName(f, isSetter);
            assert(isSetter
                    ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
                    : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
            Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
1293
            return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
1294 1295 1296
        }

        /**
1297
         * Produces a method handle giving write access to a reflected field.
1298
         * The type of the method handle will have a void return type.
1299 1300 1301 1302
         * If the field is static, the method handle will take a single
         * argument, of the field's value type, the value to be stored.
         * Otherwise, the two arguments will be the instance containing
         * the field, and the value to be stored.
1303
         * If the field's {@code accessible} flag is not set,
1304
         * access checking is performed immediately on behalf of the lookup class.
1305 1306 1307 1308
         * <p>
         * If the field is static, and
         * if the returned method handle is invoked, the field's class will
         * be initialized, if it has not already been initialized.
1309 1310
         * @param f the reflected field
         * @return a method handle which can store values into the reflected field
1311 1312
         * @throws IllegalAccessException if access checking fails
         * @throws NullPointerException if the argument is null
1313
         */
1314
        public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
1315
            return unreflectField(f, true);
1316 1317
        }

R
rfield 已提交
1318
        /**
1319 1320
         * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
         * created by this lookup object or a similar one.
R
rfield 已提交
1321 1322 1323 1324
         * Security and access checks are performed to ensure that this lookup object
         * is capable of reproducing the target method handle.
         * This means that the cracking may fail if target is a direct method handle
         * but was created by an unrelated lookup object.
1325 1326
         * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>
         * and was created by a lookup object for a different class.
R
rfield 已提交
1327 1328 1329 1330 1331 1332
         * @param target a direct method handle to crack into symbolic reference components
         * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
         * @exception SecurityException if a security manager is present and it
         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
         * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
         * @exception NullPointerException if the target is {@code null}
1333
         * @see MethodHandleInfo
R
rfield 已提交
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
         * @since 1.8
         */
        public MethodHandleInfo revealDirect(MethodHandle target) {
            MemberName member = target.internalMemberName();
            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
                throw newIllegalArgumentException("not a direct method handle");
            Class<?> defc = member.getDeclaringClass();
            byte refKind = member.getReferenceKind();
            assert(MethodHandleNatives.refKindIsValid(refKind));
            if (refKind == REF_invokeSpecial && !target.isInvokeSpecial())
                // Devirtualized method invocation is usually formally virtual.
                // To avoid creating extra MemberName objects for this common case,
                // we encode this extra degree of freedom using MH.isInvokeSpecial.
                refKind = REF_invokeVirtual;
            if (refKind == REF_invokeVirtual && defc.isInterface())
                // Symbolic reference is through interface but resolves to Object method (toString, etc.)
                refKind = REF_invokeInterface;
            // Check SM permissions and member access before cracking.
            try {
                checkAccess(refKind, defc, member);
1354
                checkSecurityManager(defc, member);
R
rfield 已提交
1355 1356 1357
            } catch (IllegalAccessException ex) {
                throw new IllegalArgumentException(ex);
            }
1358 1359 1360 1361 1362
            if (allowedModes != TRUSTED && member.isCallerSensitive()) {
                Class<?> callerClass = target.internalCallerClass();
                if (!hasPrivateAccess() || callerClass != lookupClass())
                    throw new IllegalArgumentException("method handle is caller sensitive: "+callerClass);
            }
R
rfield 已提交
1363 1364 1365 1366
            // Produce the handle to the results.
            return new InfoFromMemberName(this, member, refKind);
        }

1367
        /// Helper methods, all package-private.
1368

1369
        MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1370
            checkSymbolicClass(refc);  // do this before attempting to resolve
1371 1372
            name.getClass();  // NPE
            type.getClass();  // NPE
1373
            return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
1374
                                            NoSuchFieldException.class);
1375
        }
1376

1377
        MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1378
            checkSymbolicClass(refc);  // do this before attempting to resolve
1379 1380
            name.getClass();  // NPE
            type.getClass();  // NPE
1381
            checkMethodName(refKind, name);  // NPE check on name
1382
            return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
1383
                                            NoSuchMethodException.class);
1384
        }
1385

1386 1387 1388 1389 1390 1391 1392 1393
        MemberName resolveOrFail(byte refKind, MemberName member) throws ReflectiveOperationException {
            checkSymbolicClass(member.getDeclaringClass());  // do this before attempting to resolve
            member.getName().getClass();  // NPE
            member.getType().getClass();  // NPE
            return IMPL_NAMES.resolveOrFail(refKind, member, lookupClassOrNull(),
                                            ReflectiveOperationException.class);
        }

1394
        void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
1395
            refc.getClass();  // NPE
1396
            Class<?> caller = lookupClassOrNull();
1397
            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes))
1398
                throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
1399 1400
        }

1401
        /** Check name for an illegal leading "&lt;" character. */
1402 1403 1404 1405 1406 1407
        void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
            if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
                throw new NoSuchMethodException("illegal method name: "+name);
        }


1408 1409 1410
        /**
         * Find my trustable caller class if m is a caller sensitive method.
         * If this lookup object has private access, then the caller class is the lookupClass.
1411
         * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
1412
         */
1413
        Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
1414 1415
            Class<?> callerClass = null;
            if (MethodHandleNatives.isCallerSensitive(m)) {
1416 1417
                // Only lookups with private access are allowed to resolve caller-sensitive methods
                if (hasPrivateAccess()) {
1418 1419 1420 1421
                    callerClass = lookupClass;
                } else {
                    throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
                }
1422 1423 1424
            }
            return callerClass;
        }
1425

1426
        private boolean hasPrivateAccess() {
1427 1428 1429
            return (allowedModes & PRIVATE) != 0;
        }

1430 1431
        /**
         * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
1432 1433
         * Determines a trustable caller class to compare with refc, the symbolic reference class.
         * If this lookup object has private access, then the caller class is the lookupClass.
1434
         */
1435
        void checkSecurityManager(Class<?> refc, MemberName m) {
1436 1437 1438
            SecurityManager smgr = System.getSecurityManager();
            if (smgr == null)  return;
            if (allowedModes == TRUSTED)  return;
1439

1440
            // Step 1:
1441 1442
            boolean fullPowerLookup = hasPrivateAccess();
            if (!fullPowerLookup ||
1443 1444 1445
                !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
                ReflectUtil.checkPackageAccess(refc);
            }
1446

1447
            // Step 2:
1448
            if (m.isPublic()) return;
1449 1450
            if (!fullPowerLookup) {
                smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
1451 1452
            }

1453
            // Step 3:
1454 1455
            Class<?> defc = m.getDeclaringClass();
            if (!fullPowerLookup && defc != refc) {
1456 1457
                ReflectUtil.checkPackageAccess(defc);
            }
1458 1459
        }

1460 1461
        void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
            boolean wantStatic = (refKind == REF_invokeStatic);
1462 1463 1464 1465 1466 1467 1468 1469
            String message;
            if (m.isConstructor())
                message = "expected a method, not a constructor";
            else if (!m.isMethod())
                message = "expected a method";
            else if (wantStatic != m.isStatic())
                message = wantStatic ? "expected a static method" : "expected a non-static method";
            else
1470
                { checkAccess(refKind, refc, m); return; }
1471
            throw m.makeAccessException(message, this);
1472 1473
        }

1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
        void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
            boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind);
            String message;
            if (wantStatic != m.isStatic())
                message = wantStatic ? "expected a static field" : "expected a non-static field";
            else
                { checkAccess(refKind, refc, m); return; }
            throw m.makeAccessException(message, this);
        }

1484
        /** Check public/protected/private bits on the symbolic reference class and its member. */
1485 1486 1487 1488
        void checkAccess(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
            assert(m.referenceKindIsConsistentWith(refKind) &&
                   MethodHandleNatives.refKindIsValid(refKind) &&
                   (MethodHandleNatives.refKindIsField(refKind) == m.isField()));
1489 1490 1491
            int allowedModes = this.allowedModes;
            if (allowedModes == TRUSTED)  return;
            int mods = m.getModifiers();
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
            if (Modifier.isProtected(mods) &&
                    refKind == REF_invokeVirtual &&
                    m.getDeclaringClass() == Object.class &&
                    m.getName().equals("clone") &&
                    refc.isArray()) {
                // The JVM does this hack also.
                // (See ClassVerifier::verify_invoke_instructions
                // and LinkResolver::check_method_accessability.)
                // Because the JVM does not allow separate methods on array types,
                // there is no separate method for int[].clone.
                // All arrays simply inherit Object.clone.
                // But for access checking logic, we make Object.clone
                // (normally protected) appear to be public.
                // Later on, when the DirectMethodHandle is created,
                // its leading argument will be restricted to the
                // requested array type.
                // N.B. The return type is not adjusted, because
                // that is *not* the bytecode behavior.
                mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
            }
1512 1513 1514 1515
            if (Modifier.isProtected(mods) && refKind == REF_newInvokeSpecial) {
                // cannot "new" a protected ctor in a different package
                mods ^= Modifier.PROTECTED;
            }
1516 1517 1518
            if (Modifier.isFinal(mods) &&
                    MethodHandleNatives.refKindIsSetter(refKind))
                throw m.makeAccessException("unexpected set of a final field", this);
1519
            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
1520 1521
                return;  // common case
            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
1522 1523 1524 1525 1526
            if ((requestedModes & allowedModes) != 0) {
                if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
                                                    mods, lookupClass(), allowedModes))
                    return;
            } else {
1527
                // Protected members can also be checked as if they were package-private.
1528 1529 1530 1531
                if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
                        && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
                    return;
            }
1532
            throw m.makeAccessException(accessFailedMessage(refc, m), this);
1533 1534 1535 1536 1537
        }

        String accessFailedMessage(Class<?> refc, MemberName m) {
            Class<?> defc = m.getDeclaringClass();
            int mods = m.getModifiers();
1538 1539 1540 1541 1542
            // check the class first:
            boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
                               (defc == refc ||
                                Modifier.isPublic(refc.getModifiers())));
            if (!classOK && (allowedModes & PACKAGE) != 0) {
1543
                classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) &&
1544
                           (defc == refc ||
1545
                            VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES)));
1546 1547
            }
            if (!classOK)
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
                return "class is not public";
            if (Modifier.isPublic(mods))
                return "access to public member failed";  // (how?)
            if (Modifier.isPrivate(mods))
                return "member is private";
            if (Modifier.isProtected(mods))
                return "member is protected";
            return "member is private to package";
        }

1558 1559
        private static final boolean ALLOW_NESTMATE_ACCESS = false;

1560 1561
        private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
            int allowedModes = this.allowedModes;
1562
            if (allowedModes == TRUSTED)  return;
1563
            if (!hasPrivateAccess()
1564 1565 1566
                || (specialCaller != lookupClass()
                    && !(ALLOW_NESTMATE_ACCESS &&
                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
1567 1568
                throw new MemberName(specialCaller).
                    makeAccessException("no private access for invokespecial", this);
1569 1570
        }

1571
        private boolean restrictProtectedReceiver(MemberName method) {
1572 1573 1574 1575
            // The accessing class only has the right to use a protected member
            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
            if (!method.isProtected() || method.isStatic()
                || allowedModes == TRUSTED
1576
                || method.getDeclaringClass() == lookupClass()
1577
                || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
1578 1579
                || (ALLOW_NESTMATE_ACCESS &&
                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
1580 1581
                return false;
            return true;
1582
        }
1583
        private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
1584
            assert(!method.isStatic());
1585 1586
            // receiver type of mh is too wide; narrow to caller
            if (!method.getDeclaringClass().isAssignableFrom(caller)) {
1587
                throw method.makeAccessException("caller class must be a subclass below the method", caller);
1588
            }
1589 1590 1591
            MethodType rawType = mh.type();
            if (rawType.parameterType(0) == caller)  return mh;
            MethodType narrowType = rawType.changeParameterType(0, caller);
1592 1593 1594
            assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
            assert(mh.viewAsTypeChecks(narrowType, true));
            return mh.copyWith(narrowType, mh.form);
1595 1596
        }

1597
        /** Check access and get the requested method. */
1598
        private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
1599 1600 1601
            final boolean doRestrict    = true;
            final boolean checkSecurity = true;
            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
1602
        }
1603
        /** Check access and get the requested method, eliding receiver narrowing rules. */
1604
        private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
1605 1606 1607 1608 1609 1610 1611 1612 1613
            final boolean doRestrict    = false;
            final boolean checkSecurity = true;
            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
        }
        /** Check access and get the requested method, eliding security manager checks. */
        private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
            final boolean doRestrict    = true;
            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
1614
        }
1615
        /** Common code for all methods; do not call directly except from immediately above. */
1616
        private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
1617
                                                   boolean checkSecurity,
1618
                                                   boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
1619
            checkMethod(refKind, refc, method);
1620 1621 1622
            // Optionally check with the security manager; this isn't needed for unreflect* calls.
            if (checkSecurity)
                checkSecurityManager(refc, method);
R
rfield 已提交
1623
            assert(!method.isMethodHandleInvoke());
1624 1625 1626

            if (refKind == REF_invokeSpecial &&
                refc != lookupClass() &&
R
rfield 已提交
1627
                !refc.isInterface() &&
1628
                refc != lookupClass().getSuperclass() &&
1629 1630 1631 1632 1633
                refc.isAssignableFrom(lookupClass())) {
                assert(!method.getName().equals("<init>"));  // not this code path
                // Per JVMS 6.5, desc. of invokespecial instruction:
                // If the method is in a superclass of the LC,
                // and if our original search was above LC.super,
1634 1635 1636
                // repeat the search (symbolic lookup) from LC.super
                // and continue with the direct superclass of that class,
                // and so forth, until a match is found or no further superclasses exist.
1637
                // FIXME: MemberName.resolve should handle this instead.
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
                Class<?> refcAsSuper = lookupClass();
                MemberName m2;
                do {
                    refcAsSuper = refcAsSuper.getSuperclass();
                    m2 = new MemberName(refcAsSuper,
                                        method.getName(),
                                        method.getMethodType(),
                                        REF_invokeSpecial);
                    m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
                } while (m2 == null &&         // no method is found yet
                         refc != refcAsSuper); // search up to refc
1649 1650 1651 1652 1653 1654 1655
                if (m2 == null)  throw new InternalError(method.toString());
                method = m2;
                refc = refcAsSuper;
                // redo basic checks
                checkMethod(refKind, refc, method);
            }

1656 1657
            DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method);
            MethodHandle mh = dmh;
1658 1659 1660 1661
            // Optionally narrow the receiver argument to refc using restrictReceiver.
            if (doRestrict &&
                   (refKind == REF_invokeSpecial ||
                       (MethodHandleNatives.refKindHasReceiver(refKind) &&
1662 1663 1664 1665 1666
                           restrictProtectedReceiver(method)))) {
                mh = restrictReceiver(method, dmh, lookupClass());
            }
            mh = maybeBindCaller(method, mh, callerClass);
            mh = mh.setVarargs(method);
1667 1668
            return mh;
        }
1669 1670 1671
        private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
                                             Class<?> callerClass)
                                             throws IllegalAccessException {
1672 1673 1674
            if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method))
                return mh;
            Class<?> hostClass = lookupClass;
1675
            if (!hasPrivateAccess())  // caller must have private access
1676
                hostClass = callerClass;  // callerClass came from a security manager style stack walk
1677 1678 1679 1680
            MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass);
            // Note: caller will apply varargs after this step happens.
            return cbmh;
        }
1681
        /** Check access and get the requested field. */
1682
        private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
            final boolean checkSecurity = true;
            return getDirectFieldCommon(refKind, refc, field, checkSecurity);
        }
        /** Check access and get the requested field, eliding security manager checks. */
        private MethodHandle getDirectFieldNoSecurityManager(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
            return getDirectFieldCommon(refKind, refc, field, checkSecurity);
        }
        /** Common code for all fields; do not call directly except from immediately above. */
        private MethodHandle getDirectFieldCommon(byte refKind, Class<?> refc, MemberName field,
                                                  boolean checkSecurity) throws IllegalAccessException {
1694
            checkField(refKind, refc, field);
1695 1696 1697
            // Optionally check with the security manager; this isn't needed for unreflect* calls.
            if (checkSecurity)
                checkSecurityManager(refc, field);
1698
            DirectMethodHandle dmh = DirectMethodHandle.make(refc, field);
1699 1700 1701
            boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
                                    restrictProtectedReceiver(field));
            if (doRestrict)
1702 1703
                return restrictReceiver(field, dmh, lookupClass());
            return dmh;
1704
        }
1705
        /** Check access and get the requested constructor. */
1706
        private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717
            final boolean checkSecurity = true;
            return getDirectConstructorCommon(refc, ctor, checkSecurity);
        }
        /** Check access and get the requested constructor, eliding security manager checks. */
        private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
            return getDirectConstructorCommon(refc, ctor, checkSecurity);
        }
        /** Common code for all constructors; do not call directly except from immediately above. */
        private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
                                                  boolean checkSecurity) throws IllegalAccessException {
1718 1719
            assert(ctor.isConstructor());
            checkAccess(REF_newInvokeSpecial, refc, ctor);
1720 1721 1722
            // Optionally check with the security manager; this isn't needed for unreflect* calls.
            if (checkSecurity)
                checkSecurityManager(refc, ctor);
1723
            assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
1724
            return DirectMethodHandle.make(ctor).setVarargs(ctor);
1725
        }
1726 1727 1728 1729

        /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
         */
        /*non-public*/
1730
        MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException {
1731 1732 1733 1734 1735 1736 1737 1738
            if (!(type instanceof Class || type instanceof MethodType))
                throw new InternalError("unresolved MemberName");
            MemberName member = new MemberName(refKind, defc, name, type);
            MethodHandle mh = LOOKASIDE_TABLE.get(member);
            if (mh != null) {
                checkSymbolicClass(defc);
                return mh;
            }
1739 1740 1741 1742 1743 1744 1745
            // Treat MethodHandle.invoke and invokeExact specially.
            if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
                mh = findVirtualForMH(member.getName(), member.getMethodType());
                if (mh != null) {
                    return mh;
                }
            }
1746
            MemberName resolved = resolveOrFail(refKind, member);
1747
            mh = getDirectMethodForConstant(refKind, defc, resolved);
1748 1749 1750 1751 1752 1753 1754 1755 1756
            if (mh instanceof DirectMethodHandle
                    && canBeCached(refKind, defc, resolved)) {
                MemberName key = mh.internalMemberName();
                if (key != null) {
                    key = key.asNormalOriginal();
                }
                if (member.equals(key)) {  // better safe than sorry
                    LOOKASIDE_TABLE.put(key, (DirectMethodHandle) mh);
                }
1757
            }
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792
            return mh;
        }
        private
        boolean canBeCached(byte refKind, Class<?> defc, MemberName member) {
            if (refKind == REF_invokeSpecial) {
                return false;
            }
            if (!Modifier.isPublic(defc.getModifiers()) ||
                    !Modifier.isPublic(member.getDeclaringClass().getModifiers()) ||
                    !member.isPublic() ||
                    member.isCallerSensitive()) {
                return false;
            }
            ClassLoader loader = defc.getClassLoader();
            if (!sun.misc.VM.isSystemDomainLoader(loader)) {
                ClassLoader sysl = ClassLoader.getSystemClassLoader();
                boolean found = false;
                while (sysl != null) {
                    if (loader == sysl) { found = true; break; }
                    sysl = sysl.getParent();
                }
                if (!found) {
                    return false;
                }
            }
            try {
                MemberName resolved2 = publicLookup().resolveOrFail(refKind,
                    new MemberName(refKind, defc, member.getName(), member.getType()));
                checkSecurityManager(defc, resolved2);
            } catch (ReflectiveOperationException | SecurityException ex) {
                return false;
            }
            return true;
        }
        private
1793 1794
        MethodHandle getDirectMethodForConstant(byte refKind, Class<?> defc, MemberName member)
                throws ReflectiveOperationException {
1795
            if (MethodHandleNatives.refKindIsField(refKind)) {
1796
                return getDirectFieldNoSecurityManager(refKind, defc, member);
1797
            } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
1798
                return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass);
1799
            } else if (refKind == REF_newInvokeSpecial) {
1800
                return getDirectConstructorNoSecurityManager(defc, member);
1801 1802
            }
            // oops
1803
            throw newIllegalArgumentException("bad MethodHandle constant #"+member);
1804
        }
1805 1806

        static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>();
1807 1808 1809
    }

    /**
1810
     * Produces a method handle giving read access to elements of an array.
1811 1812 1813 1814 1815
     * The type of the method handle will have a return type of the array's
     * element type.  Its first argument will be the array type,
     * and the second will be {@code int}.
     * @param arrayClass an array type
     * @return a method handle which can load values from the given array type
1816
     * @throws NullPointerException if the argument is null
1817 1818 1819 1820
     * @throws  IllegalArgumentException if arrayClass is not an array type
     */
    public static
    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
1821
        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
1822 1823 1824
    }

    /**
1825
     * Produces a method handle giving write access to elements of an array.
1826 1827 1828
     * The type of the method handle will have a void return type.
     * Its last argument will be the array's element type.
     * The first and second arguments will be the array type and int.
1829
     * @param arrayClass the class of an array
1830
     * @return a method handle which can store values into the array type
1831
     * @throws NullPointerException if the argument is null
1832 1833 1834 1835
     * @throws IllegalArgumentException if arrayClass is not an array type
     */
    public static
    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
1836
        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
1837 1838 1839 1840 1841
    }

    /// method handle invocation (reflective style)

    /**
1842
     * Produces a method handle which will invoke any method handle of the
1843 1844
     * given {@code type}, with a given number of trailing arguments replaced by
     * a single trailing {@code Object[]} array.
1845 1846 1847 1848
     * The resulting invoker will be a method handle with the following
     * arguments:
     * <ul>
     * <li>a single {@code MethodHandle} target
1849 1850
     * <li>zero or more leading values (counted by {@code leadingArgCount})
     * <li>an {@code Object[]} array containing trailing arguments
1851
     * </ul>
1852
     * <p>
1853
     * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with
1854 1855
     * the indicated {@code type}.
     * That is, if the target is exactly of the given {@code type}, it will behave
1856
     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
1857 1858 1859
     * is used to convert the target to the required {@code type}.
     * <p>
     * The type of the returned invoker will not be the given {@code type}, but rather
1860 1861 1862
     * will have all parameters except the first {@code leadingArgCount}
     * replaced by a single array of type {@code Object[]}, which will be
     * the final parameter.
1863
     * <p>
1864
     * Before invoking its target, the invoker will spread the final array, apply
1865
     * reference casts as necessary, and unbox and widen primitive arguments.
1866 1867 1868
     * If, when the invoker is called, the supplied array argument does
     * not have the correct number of elements, the invoker will throw
     * an {@link IllegalArgumentException} instead of invoking the target.
1869 1870
     * <p>
     * This method is equivalent to the following code (though it may be more efficient):
1871
     * <blockquote><pre>{@code
1872
MethodHandle invoker = MethodHandles.invoker(type);
1873
int spreadArgCount = type.parameterCount() - leadingArgCount;
1874 1875
invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker;
1876
     * }</pre></blockquote>
1877
     * This method throws no reflective or security exceptions.
1878
     * @param type the desired target type
1879
     * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
1880
     * @return a method handle suitable for invoking any method handle of the given type
1881 1882
     * @throws NullPointerException if {@code type} is null
     * @throws IllegalArgumentException if {@code leadingArgCount} is not in
1883 1884 1885
     *                  the range from 0 to {@code type.parameterCount()} inclusive,
     *                  or if the resulting method handle's type would have
     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
1886 1887
     */
    static public
1888 1889
    MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
        if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
1890
            throw newIllegalArgumentException("bad argument count", leadingArgCount);
1891
        type = type.asSpreaderType(Object[].class, type.parameterCount() - leadingArgCount);
1892
        return type.invokers().spreadInvoker(leadingArgCount);
1893 1894 1895
    }

    /**
1896
     * Produces a special <em>invoker method handle</em> which can be used to
1897
     * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
1898
     * The resulting invoker will have a type which is
1899 1900 1901
     * exactly equal to the desired type, except that it will accept
     * an additional leading argument of type {@code MethodHandle}.
     * <p>
1902
     * This method is equivalent to the following code (though it may be more efficient):
1903
     * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
1904 1905 1906 1907 1908 1909 1910 1911
     *
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
     * Invoker method handles can be useful when working with variable method handles
     * of unknown types.
     * For example, to emulate an {@code invokeExact} call to a variable method
     * handle {@code M}, extract its type {@code T},
     * look up the invoker method {@code X} for {@code T},
1912
     * and call the invoker method, as {@code X.invoke(T, A...)}.
1913 1914 1915 1916 1917
     * (It would not work to call {@code X.invokeExact}, since the type {@code T}
     * is unknown.)
     * If spreading, collecting, or other argument transformations are required,
     * they can be applied once to the invoker {@code X} and reused on many {@code M}
     * method handle values, as long as they are compatible with the type of {@code X}.
1918
     * <p style="font-size:smaller;">
1919
     * <em>(Note:  The invoker method is not available via the Core Reflection API.
1920
     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
1921
     * on the declared {@code invokeExact} or {@code invoke} method will raise an
1922 1923 1924
     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
     * <p>
     * This method throws no reflective or security exceptions.
1925 1926
     * @param type the desired target type
     * @return a method handle suitable for invoking any method handle of the given type
1927 1928
     * @throws IllegalArgumentException if the resulting method handle's type would have
     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
1929 1930 1931
     */
    static public
    MethodHandle exactInvoker(MethodType type) {
1932
        return type.invokers().exactInvoker();
1933 1934
    }

1935 1936
    /**
     * Produces a special <em>invoker method handle</em> which can be used to
1937
     * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
1938 1939 1940 1941
     * The resulting invoker will have a type which is
     * exactly equal to the desired type, except that it will accept
     * an additional leading argument of type {@code MethodHandle}.
     * <p>
1942 1943
     * Before invoking its target, if the target differs from the expected type,
     * the invoker will apply reference casts as
1944 1945 1946 1947
     * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
     * Similarly, the return value will be converted as necessary.
     * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
     * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
1948
     * <p>
1949 1950 1951 1952 1953
     * This method is equivalent to the following code (though it may be more efficient):
     * {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)}
     * <p style="font-size:smaller;">
     * <em>Discussion:</em>
     * A {@linkplain MethodType#genericMethodType general method type} is one which
1954 1955 1956
     * mentions only {@code Object} arguments and return values.
     * An invoker for such a type is capable of calling any method handle
     * of the same arity as the general type.
1957 1958 1959 1960 1961
     * <p style="font-size:smaller;">
     * <em>(Note:  The invoker method is not available via the Core Reflection API.
     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
     * on the declared {@code invokeExact} or {@code invoke} method will raise an
     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
1962 1963 1964 1965
     * <p>
     * This method throws no reflective or security exceptions.
     * @param type the desired target type
     * @return a method handle suitable for invoking any method handle convertible to the given type
1966 1967
     * @throws IllegalArgumentException if the resulting method handle's type would have
     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
1968 1969
     */
    static public
1970
    MethodHandle invoker(MethodType type) {
1971
        return type.invokers().genericInvoker();
1972 1973
    }

1974 1975
    static /*non-public*/
    MethodHandle basicInvoker(MethodType type) {
1976
        return type.invokers().basicInvoker();
1977 1978
    }

1979
     /// method handle modification (creation from other method handles)
1980 1981

    /**
1982
     * Produces a method handle which adapts the type of the
1983
     * given method handle to a new type by pairwise argument and return type conversion.
1984 1985 1986 1987 1988 1989
     * The original type and new type must have the same number of arguments.
     * The resulting method handle is guaranteed to report a type
     * which is equal to the desired new type.
     * <p>
     * If the original type and new type are equal, returns target.
     * <p>
1990
     * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType},
1991
     * and some additional conversions are also applied if those conversions fail.
1992 1993
     * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied
     * if possible, before or instead of any conversions done by {@code asType}:
1994
     * <ul>
1995 1996
     * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type,
     *     then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast.
1997
     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
1998 1999
     * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive,
     *     the boolean is converted to a byte value, 1 for true, 0 for false.
2000
     *     (This treatment follows the usage of the bytecode verifier.)
2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
     * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive,
     *     <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5),
     *     and the low order bit of the result is tested, as if by {@code (x & 1) != 0}.
     * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean,
     *     then a Java casting conversion (JLS 5.5) is applied.
     *     (Specifically, <em>T0</em> will convert to <em>T1</em> by
     *     widening and/or narrowing.)
     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
     *     conversion will be applied at runtime, possibly followed
     *     by a Java casting conversion (JLS 5.5) on the primitive value,
     *     possibly followed by a conversion from byte to boolean by testing
     *     the low-order bit.
     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive,
     *     and if the reference is null at runtime, a zero value is introduced.
2015 2016 2017
     * </ul>
     * @param target the method handle to invoke after arguments are retyped
     * @param newType the expected type of the new method handle
2018
     * @return a method handle which delegates to the target after performing
2019 2020
     *           any necessary argument conversions, and arranges for any
     *           necessary return value conversions
2021
     * @throws NullPointerException if either argument is null
2022 2023 2024 2025 2026
     * @throws WrongMethodTypeException if the conversion cannot be made
     * @see MethodHandle#asType
     */
    public static
    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
2027
        explicitCastArgumentsChecks(target, newType);
2028
        // use the asTypeCache when possible:
2029
        MethodType oldType = target.type();
2030 2031 2032
        if (oldType == newType)  return target;
        if (oldType.explicitCastEquivalentToAsType(newType)) {
            return target.asType(newType);
2033
        }
2034
        return MethodHandleImpl.makePairwiseConvert(target, newType, false);
2035 2036
    }

2037 2038 2039 2040 2041 2042
    private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) {
        if (target.type().parameterCount() != newType.parameterCount()) {
            throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType);
        }
    }

2043
    /**
2044
     * Produces a method handle which adapts the calling sequence of the
2045
     * given method handle to a new type, by reordering the arguments.
2046
     * The resulting method handle is guaranteed to report a type
2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
     * which is equal to the desired new type.
     * <p>
     * The given array controls the reordering.
     * Call {@code #I} the number of incoming parameters (the value
     * {@code newType.parameterCount()}, and call {@code #O} the number
     * of outgoing parameters (the value {@code target.type().parameterCount()}).
     * Then the length of the reordering array must be {@code #O},
     * and each element must be a non-negative number less than {@code #I}.
     * For every {@code N} less than {@code #O}, the {@code N}-th
     * outgoing argument will be taken from the {@code I}-th incoming
     * argument, where {@code I} is {@code reorder[N]}.
     * <p>
2059 2060
     * No argument or return value conversions are applied.
     * The type of each incoming argument, as determined by {@code newType},
2061 2062
     * must be identical to the type of the corresponding outgoing parameter
     * or parameters in the target method handle.
2063 2064 2065
     * The return type of {@code newType} must be identical to the return
     * type of the original target.
     * <p>
2066 2067 2068 2069
     * The reordering array need not specify an actual permutation.
     * An incoming argument will be duplicated if its index appears
     * more than once in the array, and an incoming argument will be dropped
     * if its index does not appear in the array.
2070 2071 2072
     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
     * incoming arguments which are not mentioned in the reordering array
     * are may be any type, as determined only by {@code newType}.
A
alanb 已提交
2073
     * <blockquote><pre>{@code
2074 2075 2076 2077 2078
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodType intfn1 = methodType(int.class, int.class);
MethodType intfn2 = methodType(int.class, int.class, int.class);
2079
MethodHandle sub = ... (int x, int y) -> (x-y) ...;
2080
assert(sub.type().equals(intfn2));
2081 2082
MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
2083
assert((int)rsub.invokeExact(1, 100) == 99);
2084
MethodHandle add = ... (int x, int y) -> (x+y) ...;
2085
assert(add.type().equals(intfn2));
2086
MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
2087 2088
assert(twice.type().equals(intfn1));
assert((int)twice.invokeExact(21) == 42);
A
alanb 已提交
2089
     * }</pre></blockquote>
2090 2091
     * @param target the method handle to invoke after arguments are reordered
     * @param newType the expected type of the new method handle
2092 2093
     * @param reorder an index array which controls the reordering
     * @return a method handle which delegates to the target after it
2094
     *           drops unused arguments and moves and/or duplicates the other arguments
2095
     * @throws NullPointerException if any argument is null
2096 2097 2098 2099 2100
     * @throws IllegalArgumentException if the index array length is not equal to
     *                  the arity of the target, or if any index array element
     *                  not a valid index for a parameter of {@code newType},
     *                  or if two corresponding parameter types in
     *                  {@code target.type()} and {@code newType} are not identical,
2101 2102
     */
    public static
2103
    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
        reorder = reorder.clone();  // get a private copy
        MethodType oldType = target.type();
        permuteArgumentChecks(reorder, newType, oldType);
        if (USE_LAMBDA_FORM_EDITOR) {
            // first detect dropped arguments and handle them separately
            int[] originalReorder = reorder;
            BoundMethodHandle result = target.rebind();
            LambdaForm form = result.form;
            int newArity = newType.parameterCount();
            // Normalize the reordering into a real permutation,
            // by removing duplicates and adding dropped elements.
            // This somewhat improves lambda form caching, as well
            // as simplifying the transform by breaking it up into steps.
            for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) {
                if (ddIdx > 0) {
                    // We found a duplicated entry at reorder[ddIdx].
                    // Example:  (x,y,z)->asList(x,y,z)
                    // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1)
                    // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0)
                    // The starred element corresponds to the argument
                    // deleted by the dupArgumentForm transform.
                    int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos];
                    boolean killFirst = false;
                    for (int val; (val = reorder[--dstPos]) != dupVal; ) {
                        // Set killFirst if the dup is larger than an intervening position.
                        // This will remove at least one inversion from the permutation.
                        if (dupVal > val) killFirst = true;
                    }
                    if (!killFirst) {
                        srcPos = dstPos;
                        dstPos = ddIdx;
                    }
                    form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos);
                    assert (reorder[srcPos] == reorder[dstPos]);
                    oldType = oldType.dropParameterTypes(dstPos, dstPos + 1);
                    // contract the reordering by removing the element at dstPos
                    int tailPos = dstPos + 1;
                    System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos);
                    reorder = Arrays.copyOf(reorder, reorder.length - 1);
                } else {
                    int dropVal = ~ddIdx, insPos = 0;
                    while (insPos < reorder.length && reorder[insPos] < dropVal) {
                        // Find first element of reorder larger than dropVal.
                        // This is where we will insert the dropVal.
                        insPos += 1;
                    }
                    Class<?> ptype = newType.parameterType(dropVal);
                    form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype));
                    oldType = oldType.insertParameterTypes(insPos, ptype);
                    // expand the reordering by inserting an element at insPos
                    int tailPos = insPos + 1;
                    reorder = Arrays.copyOf(reorder, reorder.length + 1);
                    System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos);
                    reorder[insPos] = dropVal;
                }
                assert (permuteArgumentChecks(reorder, newType, oldType));
            }
            assert (reorder.length == newArity);  // a perfect permutation
            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
            form = form.editor().permuteArgumentsForm(1, reorder);
            if (newType == result.type() && form == result.internalForm())
                return result;
            return result.copyWith(newType, form);
        } else {
            // first detect dropped arguments and handle them separately
            MethodHandle originalTarget = target;
            int newArity = newType.parameterCount();
            for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) {
                // dropIdx is missing from reorder; add it in at the end
                int oldArity = reorder.length;
                target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
2175
                reorder = Arrays.copyOf(reorder, oldArity + 1);
2176 2177 2178 2179 2180 2181 2182 2183
                reorder[oldArity] = dropIdx;
            }
            assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
            BoundMethodHandle result = target.rebind();
            LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList()));
            return result.copyWith(newType, form);
        }
2184 2185
    }

2186 2187 2188 2189 2190 2191 2192
    /** Return the first value in [0..newArity-1] that is not present in reorder. */
    private static int findFirstDrop(int[] reorder, int newArity) {
        final int BIT_LIMIT = 63;  // max number of bits in bit mask
        if (newArity < BIT_LIMIT) {
            long mask = 0;
            for (int arg : reorder) {
                assert(arg < newArity);
2193
                mask |= (1L << arg);
2194
            }
2195
            if (mask == (1L << newArity) - 1) {
2196 2197 2198 2199 2200 2201 2202 2203
                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
                return -1;
            }
            // find first zero
            long zeroBit = Long.lowestOneBit(~mask);
            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
            assert(zeroPos < newArity);
            return zeroPos;
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214
        } else {
            BitSet mask = new BitSet(newArity);
            for (int arg : reorder) {
                assert (arg < newArity);
                mask.set(arg);
            }
            int zeroPos = mask.nextClearBit(0);
            assert(zeroPos <= newArity);
            if (zeroPos == newArity)
                return -1;
            return zeroPos;
2215 2216 2217
        }
    }

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
    /**
     * Return an indication of any duplicate or omission in reorder.
     * If the reorder contains a duplicate entry, return the index of the second occurrence.
     * Otherwise, return ~(n), for the first n in [0..newArity-1] that is not present in reorder.
     * Otherwise, return zero.
     * If an element not in [0..newArity-1] is encountered, return reorder.length.
     */
    private static int findFirstDupOrDrop(int[] reorder, int newArity) {
        final int BIT_LIMIT = 63;  // max number of bits in bit mask
        if (newArity < BIT_LIMIT) {
            long mask = 0;
            for (int i = 0; i < reorder.length; i++) {
                int arg = reorder[i];
2231 2232 2233 2234 2235
                if (arg >= newArity) {
                    return reorder.length;
                }
                long bit = 1L << arg;
                if ((mask & bit) != 0) {
2236
                    return i;  // >0 indicates a dup
2237
                }
2238 2239
                mask |= bit;
            }
2240
            if (mask == (1L << newArity) - 1) {
2241 2242 2243 2244 2245 2246
                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
                return 0;
            }
            // find first zero
            long zeroBit = Long.lowestOneBit(~mask);
            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
2247 2248 2249 2250
            assert(zeroPos <= newArity);
            if (zeroPos == newArity) {
                return 0;
            }
2251 2252 2253 2254 2255 2256
            return ~zeroPos;
        } else {
            // same algorithm, different bit set
            BitSet mask = new BitSet(newArity);
            for (int i = 0; i < reorder.length; i++) {
                int arg = reorder[i];
2257 2258 2259 2260
                if (arg >= newArity) {
                    return reorder.length;
                }
                if (mask.get(arg)) {
2261
                    return i;  // >0 indicates a dup
2262
                }
2263 2264 2265
                mask.set(arg);
            }
            int zeroPos = mask.nextClearBit(0);
2266
            assert(zeroPos <= newArity);
2267 2268 2269 2270 2271 2272 2273
            if (zeroPos == newArity) {
                return 0;
            }
            return ~zeroPos;
        }
    }

2274
    private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) {
2275 2276 2277
        if (newType.returnType() != oldType.returnType())
            throw newIllegalArgumentException("return types do not match",
                    oldType, newType);
2278 2279 2280
        if (reorder.length == oldType.parameterCount()) {
            int limit = newType.parameterCount();
            boolean bad = false;
2281 2282
            for (int j = 0; j < reorder.length; j++) {
                int i = reorder[j];
2283 2284 2285
                if (i < 0 || i >= limit) {
                    bad = true; break;
                }
2286 2287 2288 2289 2290
                Class<?> src = newType.parameterType(i);
                Class<?> dst = oldType.parameterType(j);
                if (src != dst)
                    throw newIllegalArgumentException("parameter types do not match after reorder",
                            oldType, newType);
2291
            }
2292
            if (!bad)  return true;
2293
        }
2294
        throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
2295 2296 2297
    }

    /**
2298
     * Produces a method handle of the requested return type which returns the given
2299 2300 2301 2302 2303
     * constant value every time it is invoked.
     * <p>
     * Before the method handle is returned, the passed-in value is converted to the requested type.
     * If the requested type is primitive, widening primitive conversions are attempted,
     * else reference conversions are attempted.
2304
     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}.
2305 2306 2307
     * @param type the return type of the desired method handle
     * @param value the value to return
     * @return a method handle of the given return type and no arguments, which always returns the given value
2308 2309 2310
     * @throws NullPointerException if the {@code type} argument is null
     * @throws ClassCastException if the value cannot be converted to the required return type
     * @throws IllegalArgumentException if the given type is {@code void.class}
2311 2312 2313 2314
     */
    public static
    MethodHandle constant(Class<?> type, Object value) {
        if (type.isPrimitive()) {
2315 2316
            if (type == void.class)
                throw newIllegalArgumentException("void type");
2317
            Wrapper w = Wrapper.forPrimitiveType(type);
2318 2319 2320 2321
            value = w.convert(value, type);
            if (w.zero().equals(value))
                return zero(w, type);
            return insertArguments(identity(type), 0, value);
2322
        } else {
2323 2324 2325
            if (value == null)
                return zero(Wrapper.OBJECT, type);
            return identity(type).bindTo(value);
2326 2327 2328 2329
        }
    }

    /**
2330 2331 2332 2333 2334
     * Produces a method handle which returns its sole argument when invoked.
     * @param type the type of the sole parameter and return value of the desired method handle
     * @return a unary method handle which accepts and returns the given type
     * @throws NullPointerException if the argument is null
     * @throws IllegalArgumentException if the given type is {@code void.class}
2335 2336 2337
     */
    public static
    MethodHandle identity(Class<?> type) {
2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
        Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT);
        int pos = btw.ordinal();
        MethodHandle ident = IDENTITY_MHS[pos];
        if (ident == null) {
            ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType()));
        }
        if (ident.type().returnType() == type)
            return ident;
        // something like identity(Foo.class); do not bother to intern these
        assert(btw == Wrapper.OBJECT);
        return makeIdentity(type);
    }
    private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
    private static MethodHandle makeIdentity(Class<?> ptype) {
        MethodType mtype = MethodType.methodType(ptype, ptype);
        LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
    }
2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374

    private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
        int pos = btw.ordinal();
        MethodHandle zero = ZERO_MHS[pos];
        if (zero == null) {
            zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
        }
        if (zero.type().returnType() == rtype)
            return zero;
        assert(btw == Wrapper.OBJECT);
        return makeZero(rtype);
    }
    private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
    private static MethodHandle makeZero(Class<?> rtype) {
        MethodType mtype = MethodType.methodType(rtype);
        LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
    }

2375 2376 2377 2378 2379
    synchronized private static MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) {
        // Simulate a CAS, to avoid racy duplication of results.
        MethodHandle prev = cache[pos];
        if (prev != null) return prev;
        return cache[pos] = value;
2380 2381 2382
    }

    /**
2383 2384 2385 2386 2387 2388 2389 2390 2391
     * Provides a target method handle with one or more <em>bound arguments</em>
     * in advance of the method handle's invocation.
     * The formal parameters to the target corresponding to the bound
     * arguments are called <em>bound parameters</em>.
     * Returns a new method handle which saves away the bound arguments.
     * When it is invoked, it receives arguments for any non-bound parameters,
     * binds the saved arguments to their corresponding parameters,
     * and calls the original target.
     * <p>
2392 2393 2394
     * The type of the new method handle will drop the types for the bound
     * parameters from the original target type, since the new method handle
     * will no longer require those arguments to be supplied by its callers.
2395
     * <p>
2396 2397 2398
     * Each given argument object must match the corresponding bound parameter type.
     * If a bound parameter type is a primitive, the argument object
     * must be a wrapper, and will be unboxed to produce the primitive value.
2399
     * <p>
2400 2401 2402 2403
     * The {@code pos} argument selects which parameters are to be bound.
     * It may range between zero and <i>N-L</i> (inclusively),
     * where <i>N</i> is the arity of the target method handle
     * and <i>L</i> is the length of the values array.
2404 2405
     * @param target the method handle to invoke after the argument is inserted
     * @param pos where to insert the argument (zero for the first)
2406
     * @param values the series of arguments to insert
2407
     * @return a method handle which inserts an additional argument,
2408
     *         before calling the original method handle
2409
     * @throws NullPointerException if the target or the {@code values} array is null
2410
     * @see MethodHandle#bindTo
2411 2412
     */
    public static
2413 2414
    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
        int insCount = values.length;
2415 2416 2417
        Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos);
        if (insCount == 0)  return target;
        BoundMethodHandle result = target.rebind();
2418 2419
        for (int i = 0; i < insCount; i++) {
            Object value = values[i];
2420
            Class<?> ptype = ptypes[pos+i];
2421
            if (ptype.isPrimitive()) {
2422
                result = insertArgumentPrimitive(result, pos, ptype, value);
2423
            } else {
2424 2425
                value = ptype.cast(value);  // throw CCE if needed
                result = result.bindArgumentL(pos, value);
2426
            }
2427
        }
2428 2429 2430
        return result;
    }

2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455
    private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos,
                                                             Class<?> ptype, Object value) {
        Wrapper w = Wrapper.forPrimitiveType(ptype);
        // perform unboxing and/or primitive conversion
        value = w.convert(value, ptype);
        switch (w) {
        case INT:     return result.bindArgumentI(pos, (int)value);
        case LONG:    return result.bindArgumentJ(pos, (long)value);
        case FLOAT:   return result.bindArgumentF(pos, (float)value);
        case DOUBLE:  return result.bindArgumentD(pos, (double)value);
        default:      return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
        }
    }

    private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
        MethodType oldType = target.type();
        int outargs = oldType.parameterCount();
        int inargs  = outargs - insCount;
        if (inargs < 0)
            throw newIllegalArgumentException("too many values to insert");
        if (pos < 0 || pos > inargs)
            throw newIllegalArgumentException("no argument type to append");
        return oldType.ptypes();
    }

2456
    /**
2457 2458 2459 2460 2461
     * Produces a method handle which will discard some dummy arguments
     * before calling some other specified <i>target</i> method handle.
     * The type of the new method handle will be the same as the target's type,
     * except it will also include the dummy argument types,
     * at some given position.
2462
     * <p>
2463 2464 2465 2466 2467
     * The {@code pos} argument may range between zero and <i>N</i>,
     * where <i>N</i> is the arity of the target.
     * If {@code pos} is zero, the dummy arguments will precede
     * the target's real arguments; if {@code pos} is <i>N</i>
     * they will come after.
2468 2469
     * <p>
     * <b>Example:</b>
2470
     * <blockquote><pre>{@code
2471 2472
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
2473 2474 2475 2476
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
2477 2478 2479 2480
MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
assertEquals(bigType, d0.type());
assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
2481
     * }</pre></blockquote>
2482 2483
     * <p>
     * This method is also equivalent to the following code:
2484
     * <blockquote><pre>
2485
     * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))}
2486
     * </pre></blockquote>
2487 2488 2489 2490
     * @param target the method handle to invoke after the arguments are dropped
     * @param valueTypes the type(s) of the argument(s) to drop
     * @param pos position of first argument to drop (zero for the leftmost)
     * @return a method handle which drops arguments of the given types,
2491
     *         before calling the original method handle
2492
     * @throws NullPointerException if the target is null,
2493
     *                              or if the {@code valueTypes} list or any of its elements is null
2494 2495 2496
     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
     *                  or if {@code pos} is negative or greater than the arity of the target,
     *                  or if the new method handle's type would have too many parameters
2497 2498
     */
    public static
2499
    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
2500
        MethodType oldType = target.type();  // get NPE
2501
        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
2502
        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
2503 2504 2505
        if (dropped == 0)  return target;
        BoundMethodHandle result = target.rebind();
        LambdaForm lform = result.form;
2506 2507 2508 2509 2510 2511 2512 2513
        if (USE_LAMBDA_FORM_EDITOR) {
            int insertFormArg = 1 + pos;
            for (Class<?> ptype : valueTypes) {
                lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype));
            }
        } else {
            lform = lform.addArguments(pos, valueTypes);
        }
2514 2515 2516 2517 2518
        result = result.copyWith(newType, lform);
        return result;
    }

    private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
2519 2520
        int dropped = valueTypes.size();
        MethodType.checkSlotCount(dropped);
2521
        int outargs = oldType.parameterCount();
2522
        int inargs  = outargs + dropped;
2523 2524 2525 2526 2527
        if (pos < 0 || pos > outargs)
            throw newIllegalArgumentException("no argument type to remove"
                    + Arrays.asList(oldType, pos, valueTypes, inargs, outargs)
                    );
        return dropped;
2528 2529
    }

2530
    /**
2531 2532 2533 2534 2535
     * Produces a method handle which will discard some dummy arguments
     * before calling some other specified <i>target</i> method handle.
     * The type of the new method handle will be the same as the target's type,
     * except it will also include the dummy argument types,
     * at some given position.
2536
     * <p>
2537 2538 2539 2540 2541
     * The {@code pos} argument may range between zero and <i>N</i>,
     * where <i>N</i> is the arity of the target.
     * If {@code pos} is zero, the dummy arguments will precede
     * the target's real arguments; if {@code pos} is <i>N</i>
     * they will come after.
2542 2543
     * <p>
     * <b>Example:</b>
2544
     * <blockquote><pre>{@code
2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d1 = dropArguments(cat, 1, String.class);
assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
MethodHandle d2 = dropArguments(cat, 2, String.class);
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
2559
     * }</pre></blockquote>
2560 2561
     * <p>
     * This method is also equivalent to the following code:
2562
     * <blockquote><pre>
2563
     * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
2564
     * </pre></blockquote>
2565 2566 2567 2568 2569
     * @param target the method handle to invoke after the arguments are dropped
     * @param valueTypes the type(s) of the argument(s) to drop
     * @param pos position of first argument to drop (zero for the leftmost)
     * @return a method handle which drops arguments of the given types,
     *         before calling the original method handle
2570
     * @throws NullPointerException if the target is null,
2571
     *                              or if the {@code valueTypes} array or any of its elements is null
2572 2573
     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
     *                  or if {@code pos} is negative or greater than the arity of the target,
2574 2575
     *                  or if the new method handle's type would have
     *                  <a href="MethodHandle.html#maxarity">too many parameters</a>
2576
     */
2577 2578 2579 2580 2581 2582
    public static
    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
        return dropArguments(target, pos, Arrays.asList(valueTypes));
    }

    /**
2583
     * Adapts a target method handle by pre-processing
2584 2585 2586 2587 2588
     * one or more of its arguments, each with its own unary filter function,
     * and then calling the target with each pre-processed argument
     * replaced by the result of its corresponding filter function.
     * <p>
     * The pre-processing is performed by one or more method handles,
2589
     * specified in the elements of the {@code filters} array.
2590 2591 2592 2593 2594
     * The first element of the filter array corresponds to the {@code pos}
     * argument of the target, and so on in sequence.
     * <p>
     * Null arguments in the array are treated as identity functions,
     * and the corresponding arguments left unchanged.
2595
     * (If there are no non-null elements in the array, the original target is returned.)
2596
     * Each filter is applied to the corresponding argument of the adapter.
2597 2598
     * <p>
     * If a filter {@code F} applies to the {@code N}th argument of
2599
     * the target, then {@code F} must be a method handle which
2600 2601 2602 2603 2604 2605
     * takes exactly one argument.  The type of {@code F}'s sole argument
     * replaces the corresponding argument type of the target
     * in the resulting adapted method handle.
     * The return type of {@code F} must be identical to the corresponding
     * parameter type of the target.
     * <p>
2606
     * It is an error if there are elements of {@code filters}
2607
     * (null or not)
2608
     * which do not correspond to argument positions in the target.
2609
     * <p><b>Example:</b>
2610
     * <blockquote><pre>{@code
2611 2612
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
2613 2614 2615 2616 2617
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle upcase = lookup().findVirtual(String.class,
  "toUpperCase", methodType(String.class));
2618
assertEquals("xy", (String) cat.invokeExact("x", "y"));
2619
MethodHandle f0 = filterArguments(cat, 0, upcase);
2620
assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
2621
MethodHandle f1 = filterArguments(cat, 1, upcase);
2622
assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
2623
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
2624
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
2625
     * }</pre></blockquote>
2626
     * <p> Here is pseudocode for the resulting adapter:
2627
     * <blockquote><pre>{@code
2628 2629 2630 2631 2632
     * V target(P... p, A[i]... a[i], B... b);
     * A[i] filter[i](V[i]);
     * T adapter(P... p, V[i]... v[i], B... b) {
     *   return target(p..., f[i](v[i])..., b...);
     * }
2633
     * }</pre></blockquote>
2634
     *
2635
     * @param target the method handle to invoke after arguments are filtered
2636
     * @param pos the position of the first argument to filter
2637 2638
     * @param filters method handles to call initially on filtered arguments
     * @return method handle which incorporates the specified argument filtering logic
2639
     * @throws NullPointerException if the target is null
2640 2641
     *                              or if the {@code filters} array is null
     * @throws IllegalArgumentException if a non-null element of {@code filters}
2642
     *          does not match a corresponding argument type of target as described above,
2643 2644 2645
     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
     *          or if the resulting method handle's type would have
     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
2646 2647
     */
    public static
2648
    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
2649
        filterArgumentsCheckArity(target, pos, filters);
2650
        MethodHandle adapter = target;
2651
        int curPos = pos-1;  // pre-incremented
2652
        for (MethodHandle filter : filters) {
2653 2654
            curPos += 1;
            if (filter == null)  continue;  // ignore null elements of filters
2655
            adapter = filterArgument(adapter, curPos, filter);
2656 2657 2658 2659
        }
        return adapter;
    }

2660 2661
    /*non-public*/ static
    MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
2662
        filterArgumentChecks(target, pos, filter);
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
        if (USE_LAMBDA_FORM_EDITOR) {
            MethodType targetType = target.type();
            MethodType filterType = filter.type();
            BoundMethodHandle result = target.rebind();
            Class<?> newParamType = filterType.parameterType(0);
            LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
            MethodType newType = targetType.changeParameterType(pos, newParamType);
            result = result.copyWithExtendL(newType, lform, filter);
            return result;
        } else {
            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
        }
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
    }

    private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
        MethodType targetType = target.type();
        int maxPos = targetType.parameterCount();
        if (pos + filters.length > maxPos)
            throw newIllegalArgumentException("too many filters");
    }

    private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
2685 2686 2687 2688 2689 2690 2691
        MethodType targetType = target.type();
        MethodType filterType = filter.type();
        if (filterType.parameterCount() != 1
            || filterType.returnType() != targetType.parameterType(pos))
            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
    }

2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717
    /**
     * Adapts a target method handle by pre-processing
     * a sub-sequence of its arguments with a filter (another method handle).
     * The pre-processed arguments are replaced by the result (if any) of the
     * filter function.
     * The target is then called on the modified (usually shortened) argument list.
     * <p>
     * If the filter returns a value, the target must accept that value as
     * its argument in position {@code pos}, preceded and/or followed by
     * any arguments not passed to the filter.
     * If the filter returns void, the target must accept all arguments
     * not passed to the filter.
     * No arguments are reordered, and a result returned from the filter
     * replaces (in order) the whole subsequence of arguments originally
     * passed to the adapter.
     * <p>
     * The argument types (if any) of the filter
     * replace zero or one argument types of the target, at position {@code pos},
     * in the resulting adapted method handle.
     * The return type of the filter (if any) must be identical to the
     * argument type of the target at position {@code pos}, and that target argument
     * is supplied by the return value of the filter.
     * <p>
     * In all cases, {@code pos} must be greater than or equal to zero, and
     * {@code pos} must also be less than or equal to the target's arity.
     * <p><b>Example:</b>
2718
     * <blockquote><pre>{@code
2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle deepToString = publicLookup()
  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));

MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
assertEquals("[strange]", (String) ts1.invokeExact("strange"));

MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));

MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
assertEquals("[top, [up, down], strange]",
             (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));

MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
assertEquals("[top, [up, down], [strange]]",
             (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));

MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
assertEquals("[top, [[up, down, strange], charm], bottom]",
             (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
2743
     * }</pre></blockquote>
2744
     * <p> Here is pseudocode for the resulting adapter:
2745
     * <blockquote><pre>{@code
2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765
     * T target(A...,V,C...);
     * V filter(B...);
     * T adapter(A... a,B... b,C... c) {
     *   V v = filter(b...);
     *   return target(a...,v,c...);
     * }
     * // and if the filter has no arguments:
     * T target2(A...,V,C...);
     * V filter2();
     * T adapter2(A... a,C... c) {
     *   V v = filter2();
     *   return target2(a...,v,c...);
     * }
     * // and if the filter has a void return:
     * T target3(A...,C...);
     * void filter3(B...);
     * void adapter3(A... a,B... b,C... c) {
     *   filter3(b...);
     *   return target3(a...,c...);
     * }
2766
     * }</pre></blockquote>
2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799
     * <p>
     * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
     * one which first "folds" the affected arguments, and then drops them, in separate
     * steps as follows:
     * <blockquote><pre>{@code
     * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
     * mh = MethodHandles.foldArguments(mh, coll); //step 1
     * }</pre></blockquote>
     * If the target method handle consumes no arguments besides than the result
     * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
     * is equivalent to {@code filterReturnValue(coll, mh)}.
     * If the filter method handle {@code coll} consumes one argument and produces
     * a non-void result, then {@code collectArguments(mh, N, coll)}
     * is equivalent to {@code filterArguments(mh, N, coll)}.
     * Other equivalences are possible but would require argument permutation.
     *
     * @param target the method handle to invoke after filtering the subsequence of arguments
     * @param pos the position of the first adapter argument to pass to the filter,
     *            and/or the target argument which receives the result of the filter
     * @param filter method handle to call on the subsequence of arguments
     * @return method handle which incorporates the specified argument subsequence filtering logic
     * @throws NullPointerException if either argument is null
     * @throws IllegalArgumentException if the return type of {@code filter}
     *          is non-void and is not the same as the {@code pos} argument of the target,
     *          or if {@code pos} is not between 0 and the target's arity, inclusive,
     *          or if the resulting method handle's type would have
     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
     * @see MethodHandles#foldArguments
     * @see MethodHandles#filterArguments
     * @see MethodHandles#filterReturnValue
     */
    public static
    MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818
        MethodType newType = collectArgumentsChecks(target, pos, filter);
        if (USE_LAMBDA_FORM_EDITOR) {
            MethodType collectorType = filter.type();
            BoundMethodHandle result = target.rebind();
            LambdaForm lform;
            if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) {
                lform = result.editor().collectArgumentArrayForm(1 + pos, filter);
                if (lform != null) {
                    return result.copyWith(newType, lform);
                }
            }
            lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType());
            return result.copyWithExtendL(newType, lform, filter);
        } else {
            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
        }
    }

    private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
2819
        MethodType targetType = target.type();
2820
        MethodType filterType = filter.type();
2821 2822 2823 2824 2825 2826
        Class<?> rtype = filterType.returnType();
        List<Class<?>> filterArgs = filterType.parameterList();
        if (rtype == void.class) {
            return targetType.insertParameterTypes(pos, filterArgs);
        }
        if (rtype != targetType.parameterType(pos)) {
2827
            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
2828 2829
        }
        return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs);
2830 2831
    }

2832
    /**
2833 2834 2835
     * Adapts a target method handle by post-processing
     * its return value (if any) with a filter (another method handle).
     * The result of the filter is returned from the adapter.
2836
     * <p>
2837 2838 2839 2840 2841
     * If the target returns a value, the filter must accept that value as
     * its only argument.
     * If the target returns void, the filter must accept no arguments.
     * <p>
     * The return type of the filter
2842 2843
     * replaces the return type of the target
     * in the resulting adapted method handle.
2844
     * The argument type of the filter (if any) must be identical to the
2845
     * return type of the target.
2846
     * <p><b>Example:</b>
2847
     * <blockquote><pre>{@code
2848 2849
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
2850 2851 2852 2853 2854 2855 2856 2857
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle length = lookup().findVirtual(String.class,
  "length", methodType(int.class));
System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2
2858
     * }</pre></blockquote>
2859
     * <p> Here is pseudocode for the resulting adapter:
2860
     * <blockquote><pre>{@code
2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880
     * V target(A...);
     * T filter(V);
     * T adapter(A... a) {
     *   V v = target(a...);
     *   return filter(v);
     * }
     * // and if the target has a void return:
     * void target2(A...);
     * T filter2();
     * T adapter2(A... a) {
     *   target2(a...);
     *   return filter2();
     * }
     * // and if the filter has a void return:
     * V target3(A...);
     * void filter3(V);
     * void adapter3(A... a) {
     *   V v = target3(a...);
     *   filter3(v);
     * }
2881
     * }</pre></blockquote>
2882 2883 2884
     * @param target the method handle to invoke before filtering the return value
     * @param filter method handle to call on the return value
     * @return method handle which incorporates the specified return value filtering logic
2885
     * @throws NullPointerException if either argument is null
2886 2887
     * @throws IllegalArgumentException if the argument list of {@code filter}
     *          does not match the return type of target as described above
2888
     */
2889
    public static
2890 2891 2892
    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
        MethodType targetType = target.type();
        MethodType filterType = filter.type();
2893
        filterReturnValueChecks(targetType, filterType);
2894 2895 2896 2897 2898 2899 2900 2901 2902 2903
        if (USE_LAMBDA_FORM_EDITOR) {
            BoundMethodHandle result = target.rebind();
            BasicType rtype = BasicType.basicType(filterType.returnType());
            LambdaForm lform = result.editor().filterReturnForm(rtype, false);
            MethodType newType = targetType.changeReturnType(filterType.returnType());
            result = result.copyWithExtendL(newType, lform, filter);
            return result;
        } else {
            return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
        }
2904 2905 2906
    }

    private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException {
2907 2908 2909 2910 2911
        Class<?> rtype = targetType.returnType();
        int filterValues = filterType.parameterCount();
        if (filterValues == 0
                ? (rtype != void.class)
                : (rtype != filterType.parameterType(0)))
2912
            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
2913 2914
    }

2915
    /**
2916
     * Adapts a target method handle by pre-processing
2917
     * some of its arguments, and then calling the target with
2918 2919
     * the result of the pre-processing, inserted into the original
     * sequence of arguments.
2920
     * <p>
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
     * The pre-processing is performed by {@code combiner}, a second method handle.
     * Of the arguments passed to the adapter, the first {@code N} arguments
     * are copied to the combiner, which is then called.
     * (Here, {@code N} is defined as the parameter count of the combiner.)
     * After this, control passes to the target, with any result
     * from the combiner inserted before the original {@code N} incoming
     * arguments.
     * <p>
     * If the combiner returns a value, the first parameter type of the target
     * must be identical with the return type of the combiner, and the next
     * {@code N} parameter types of the target must exactly match the parameters
     * of the combiner.
     * <p>
     * If the combiner has a void return, no result will be inserted,
     * and the first {@code N} parameter types of the target
     * must exactly match the parameters of the combiner.
2937 2938
     * <p>
     * The resulting adapter is the same type as the target, except that the
2939 2940
     * first parameter type is dropped,
     * if it corresponds to the result of the combiner.
2941
     * <p>
2942
     * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
2943
     * that either the combiner or the target does not wish to receive.
2944
     * If some of the incoming arguments are destined only for the combiner,
2945
     * consider using {@link MethodHandle#asCollector asCollector} instead, since those
2946 2947
     * arguments will not need to be live on the stack on entry to the
     * target.)
2948
     * <p><b>Example:</b>
2949
     * <blockquote><pre>{@code
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
  "println", methodType(void.class, String.class))
    .bindTo(System.out);
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
MethodHandle catTrace = foldArguments(cat, trace);
// also prints "boo":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
2962
     * }</pre></blockquote>
2963
     * <p> Here is pseudocode for the resulting adapter:
2964
     * <blockquote><pre>{@code
2965
     * // there are N arguments in A...
2966 2967 2968 2969 2970 2971
     * T target(V, A[N]..., B...);
     * V combiner(A...);
     * T adapter(A... a, B... b) {
     *   V v = combiner(a...);
     *   return target(v, a..., b...);
     * }
2972 2973 2974 2975 2976 2977 2978
     * // and if the combiner has a void return:
     * T target2(A[N]..., B...);
     * void combiner2(A...);
     * T adapter2(A... a, B... b) {
     *   combiner2(a...);
     *   return target2(a..., b...);
     * }
2979
     * }</pre></blockquote>
2980 2981 2982
     * @param target the method handle to invoke after arguments are combined
     * @param combiner method handle to call initially on the incoming arguments
     * @return method handle which incorporates the specified argument folding logic
2983
     * @throws NullPointerException if either argument is null
2984 2985 2986 2987 2988
     * @throws IllegalArgumentException if {@code combiner}'s return type
     *          is non-void and not the same as the first argument type of
     *          the target, or if the initial {@code N} argument types
     *          of the target
     *          (skipping one matching the {@code combiner}'s return type)
2989 2990 2991 2992
     *          are not identical with the argument types of {@code combiner}
     */
    public static
    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
2993
        int foldPos = 0;
2994 2995
        MethodType targetType = target.type();
        MethodType combinerType = combiner.type();
2996
        Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009
        if (USE_LAMBDA_FORM_EDITOR) {
            BoundMethodHandle result = target.rebind();
            boolean dropResult = (rtype == void.class);
            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
            LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType());
            MethodType newType = targetType;
            if (!dropResult)
                newType = newType.dropParameterTypes(foldPos, foldPos + 1);
            result = result.copyWithExtendL(newType, lform, combiner);
            return result;
        } else {
            return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
        }
3010 3011 3012 3013 3014 3015
    }

    private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
        int foldArgs   = combinerType.parameterCount();
        Class<?> rtype = combinerType.returnType();
        int foldVals = rtype == void.class ? 0 : 1;
3016 3017 3018 3019 3020
        int afterInsertPos = foldPos + foldVals;
        boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
        if (ok && !(combinerType.parameterList()
                    .equals(targetType.parameterList().subList(afterInsertPos,
                                                               afterInsertPos + foldArgs))))
3021
            ok = false;
3022
        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
3023
            ok = false;
3024 3025
        if (!ok)
            throw misMatchedTypes("target and combiner types", targetType, combinerType);
3026
        return rtype;
3027 3028
    }

3029
    /**
3030
     * Makes a method handle which adapts a target method handle,
3031 3032 3033 3034
     * by guarding it with a test, a boolean-valued method handle.
     * If the guard fails, a fallback handle is called instead.
     * All three method handles must have the same corresponding
     * argument and return types, except that the return type
3035 3036
     * of the test must be boolean, and the test is allowed
     * to have fewer arguments than the other two method handles.
3037
     * <p> Here is pseudocode for the resulting adapter:
3038
     * <blockquote><pre>{@code
3039
     * boolean test(A...);
3040 3041 3042
     * T target(A...,B...);
     * T fallback(A...,B...);
     * T adapter(A... a,B... b) {
3043
     *   if (test(a...))
3044
     *     return target(a..., b...);
3045
     *   else
3046
     *     return fallback(a..., b...);
3047
     * }
3048
     * }</pre></blockquote>
3049 3050 3051
     * Note that the test arguments ({@code a...} in the pseudocode) cannot
     * be modified by execution of the test, and so are passed unchanged
     * from the caller to the target or fallback as appropriate.
3052 3053 3054 3055
     * @param test method handle used for test, must return boolean
     * @param target method handle to call if test passes
     * @param fallback method handle to call if test fails
     * @return method handle which incorporates the specified if/then/else logic
3056
     * @throws NullPointerException if any argument is null
3057 3058
     * @throws IllegalArgumentException if {@code test} does not return boolean,
     *          or if all three method types do not match (with the return
3059
     *          type of {@code test} changed to match that of the target).
3060 3061 3062 3063 3064
     */
    public static
    MethodHandle guardWithTest(MethodHandle test,
                               MethodHandle target,
                               MethodHandle fallback) {
3065 3066 3067
        MethodType gtype = test.type();
        MethodType ttype = target.type();
        MethodType ftype = fallback.type();
3068
        if (!ttype.equals(ftype))
3069
            throw misMatchedTypes("target and fallback types", ttype, ftype);
3070 3071 3072 3073 3074 3075 3076
        if (gtype.returnType() != boolean.class)
            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
        List<Class<?>> targs = ttype.parameterList();
        List<Class<?>> gargs = gtype.parameterList();
        if (!targs.equals(gargs)) {
            int gpc = gargs.size(), tpc = targs.size();
            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
3077
                throw misMatchedTypes("target and test types", ttype, gtype);
3078 3079
            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
            gtype = test.type();
3080
        }
3081
        return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
3082 3083
    }

3084 3085 3086 3087
    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
    }

3088
    /**
3089
     * Makes a method handle which adapts a target method handle,
3090 3091 3092 3093
     * by running it inside an exception handler.
     * If the target returns normally, the adapter returns that value.
     * If an exception matching the specified type is thrown, the fallback
     * handle is called instead on the exception, plus the original arguments.
3094
     * <p>
3095 3096 3097 3098
     * The target and handler must have the same corresponding
     * argument and return types, except that handler may omit trailing arguments
     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
3099
     * <p> Here is pseudocode for the resulting adapter:
3100
     * <blockquote><pre>{@code
3101
     * T target(A..., B...);
3102
     * T handler(ExType, A...);
3103
     * T adapter(A... a, B... b) {
3104
     *   try {
3105
     *     return target(a..., b...);
3106 3107 3108
     *   } catch (ExType ex) {
     *     return handler(ex, a...);
     *   }
3109
     * }
3110
     * }</pre></blockquote>
3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
     * be modified by execution of the target, and so are passed unchanged
     * from the caller to the handler, if the handler is invoked.
     * <p>
     * The target and handler must return the same type, even if the handler
     * always throws.  (This might happen, for instance, because the handler
     * is simulating a {@code finally} clause).
     * To create such a throwing handler, compose the handler creation logic
     * with {@link #throwException throwException},
     * in order to create a method handle of the correct return type.
3121 3122 3123 3124
     * @param target method handle to call
     * @param exType the type of exception which the handler will catch
     * @param handler method handle to call if a matching exception is thrown
     * @return method handle which incorporates the specified try/catch logic
3125
     * @throws NullPointerException if any argument is null
3126 3127 3128 3129
     * @throws IllegalArgumentException if {@code handler} does not accept
     *          the given exception type, or if the method handle types do
     *          not match in their return types and their
     *          corresponding parameters
3130 3131
     */
    public static
3132 3133 3134
    MethodHandle catchException(MethodHandle target,
                                Class<? extends Throwable> exType,
                                MethodHandle handler) {
3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148
        MethodType ttype = target.type();
        MethodType htype = handler.type();
        if (htype.parameterCount() < 1 ||
            !htype.parameterType(0).isAssignableFrom(exType))
            throw newIllegalArgumentException("handler does not accept exception type "+exType);
        if (htype.returnType() != ttype.returnType())
            throw misMatchedTypes("target and handler return types", ttype, htype);
        List<Class<?>> targs = ttype.parameterList();
        List<Class<?>> hargs = htype.parameterList();
        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
        if (!targs.equals(hargs)) {
            int hpc = hargs.size(), tpc = targs.size();
            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
                throw misMatchedTypes("target and handler types", ttype, htype);
3149
            handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc));
3150 3151
            htype = handler.type();
        }
3152
        return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
3153 3154
    }

3155
    /**
3156
     * Produces a method handle which will throw exceptions of the given {@code exType}.
3157 3158 3159 3160 3161
     * The method handle will accept a single argument of {@code exType},
     * and immediately throw it as an exception.
     * The method type will nominally specify a return of {@code returnType}.
     * The return type may be anything convenient:  It doesn't matter to the
     * method handle's behavior, since it will never return normally.
3162 3163
     * @param returnType the return type of the desired method handle
     * @param exType the parameter type of the desired method handle
3164 3165
     * @return method handle which can throw the given exceptions
     * @throws NullPointerException if either argument is null
3166 3167 3168
     */
    public static
    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
3169 3170
        if (!Throwable.class.isAssignableFrom(exType))
            throw new ClassCastException(exType.getName());
3171
        return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
3172
    }
3173
}