~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/lang/invoke/MethodHandles.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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