1 /*
   2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package java.dyn;
  27 
  28 import impl.java.dyn.Access;
  29 import impl.java.dyn.MemberName;
  30 import impl.java.dyn.MethodHandleImpl;
  31 import impl.java.dyn.util.MethodHandleInvoker;
  32 import impl.java.dyn.util.VerifyAccess;
  33 import impl.java.dyn.util.Wrappers;
  34 import java.lang.reflect.Field;
  35 import java.lang.reflect.Method;
  36 import java.lang.reflect.Modifier;
  37 import java.util.ArrayList;
  38 import java.util.Arrays;
  39 import sun.reflect.Reflection;
  40 import static impl.java.dyn.MemberName.newIllegalArgumentException;
  41 import static impl.java.dyn.MemberName.newNoAccessException;
  42 
  43 /**
  44  * Fundamental operations and utilities for MethodHandle.
  45  * <p>
  46  * <em>API Note:</em>  The matching of method types in this API cannot
  47  * be completely checked by Java's generic type system for three reasons:
  48  * <ol>
  49  * <li>Method types range over all possible arities,
  50  * from no arguments to an arbitrary number of arguments.
  51  * Generics are not variadic, and so cannot represent this.</li>
  52  * <li>Method types can specify arguments of primitive types,
  53  * which Java generic types cannot range over.</li>
  54  * <li>Method types can optionally specify varargs (ellipsis).</li>
  55  * </ol>
  56  * @author John Rose, JSR 292 EG
  57  */
  58 public class MethodHandles {
  59 
  60     private MethodHandles() { }  // do not instantiate
  61 
  62     private static final Access IMPL_TOKEN = Access.getToken();
  63     private static final MemberName.Factory IMPL_LOOKUP = MemberName.getFactory(IMPL_TOKEN);
  64 
  65     //// Method handle creation from ordinary methods.
  66 
  67     /**
  68      * Produce a method handle for a static method.
  69      * The type of the method handle will be that of the method.
  70      * The method and all its argument types must be accessible to the caller.
  71      * If the method's class has not yet been initialized, that is done
  72      * immediately, before the method handle is returned.
  73      * @param defc the class from which the method is accessed
  74      * @param name the name of the method
  75      * @param type the type of the method
  76      * @return the desired method handle, or null if no such method exists
  77      * @exception SecurityException <em>TBD</em>
  78      * @exception NoAccessException if access checking fails
  79      */
  80     public static
  81     MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
  82         Class<?> caller = Reflection.getCallerClass(2);
  83         MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, caller);
  84         checkStatic(true, method, caller);
  85         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, caller);
  86     }
  87 
  88     private static void checkStatic(boolean wantStatic, MemberName m, Class<?> caller) {
  89         if (wantStatic != m.isStatic()) {
  90             String message = wantStatic ? "expected a static method" : "expected a non-static method";
  91             throw newNoAccessException(message, m, caller);
  92         }
  93     }
  94 
  95     /**
  96      * Produce a method handle for a virtual method.
  97      * The type of the method handle will be that of the method,
  98      * with the receiver type ({@code defc}) prepended.
  99      * The method and all its argument types must be accessible to the caller.
 100      * <p>
 101      * When called, the handle will treat the first argument as a receiver
 102      * and dispatch on the receiver's type to determine which method
 103      * implementation to enter.
 104      * (The dispatching action is identical with that performed by an
 105      * {@code invokevirtual} or {@code invokeinterface} instruction.)
 106      * @param defc the class or interface from which the method is accessed
 107      * @param name the name of the method
 108      * @param type the type of the method, with the receiver argument omitted
 109      * @return the desired method handle, or null if no such method exists
 110      * @exception SecurityException <em>TBD</em>
 111      * @exception NoAccessException if access checking fails
 112      */
 113     public static
 114     MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
 115         Class<?> caller = Reflection.getCallerClass(2);
 116         MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), true, caller);
 117         checkStatic(false, method, caller);
 118         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
 119     }
 120 
 121     /**
 122      * Produce an early-bound method handle for a virtual method,
 123      * or a handle for a constructor, as if called from an {@code invokespecial}
 124      * instruction from {@code caller}.
 125      * The type of the method handle will be that of the method or constructor,
 126      * with a suitably restricted receiver type (such as {@code caller}) prepended.
 127      * The method or constructor and all its argument types must be accessible
 128      * to the caller.
 129      * <p>
 130      * When called, the handle will treat the first argument as a receiver,
 131      * but will not dispatch on the receiver's type.
 132      * (This direct invocation action is identical with that performed by an
 133      * {@code invokespecial} instruction.)
 134      * <p>
 135      * If the explicitly specified caller class is not identical with the actual
 136      * caller of {@code findSpecial}, a security check TBD is performed.
 137      * @param defc the class or interface from which the method is accessed
 138      * @param name the name of the method, or "<init>" for a constructor
 139      * @param type the type of the method, with the receiver argument omitted
 140      * @param specialCaller the proposed calling class to perform the {@code invokespecial}
 141      * @return the desired method handle, or null if no such method exists
 142      * @exception SecurityException <em>TBD</em>
 143      * @exception NoAccessException if access checking fails
 144      */
 145     public static
 146     MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
 147             Class<?> specialCaller) throws NoAccessException {
 148         Class<?> caller = Reflection.getCallerClass(2);
 149         checkSpecialCaller(specialCaller, caller);
 150         MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
 151         checkStatic(false, method, caller);
 152         if (name.equals("<init>")) {
 153             if (defc != specialCaller)
 154                 throw newNoAccessException("constructor must be local to caller", method, caller);
 155         } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
 156             throw newNoAccessException("method must be in a superclass of caller", method, caller);
 157         }
 158         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
 159     }
 160 
 161     /**
 162      * Produce an early-bound method handle for a non-static method.
 163      * The receiver must have a supertype {@code defc} in which a method
 164      * of the given name and type is accessible to the caller.
 165      * The method and all its argument types must be accessible to the caller.
 166      * The type of the method handle will be that of the method.
 167      * The given receiver will be bound into the method handle.
 168      * <p>
 169      * Equivalent to the following expression:
 170      * <code>
 171      * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
 172      * </code>
 173      * @param receiver the object from which the method is accessed
 174      * @param name the name of the method
 175      * @param type the type of the method, with the receiver argument omitted
 176      * @return the desired method handle, or null if no such method exists
 177      * @exception SecurityException <em>TBD</em>
 178      * @exception NoAccessException if access checking fails
 179      */
 180     public static
 181     MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
 182         Class<?> caller = Reflection.getCallerClass(2);
 183         Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
 184         MemberName reference = new MemberName(rcvc, name, type);
 185         MemberName method = IMPL_LOOKUP.resolveOrFail(reference, true, caller);
 186         checkStatic(false, method, caller);
 187         MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
 188         MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
 189         if (bmh == null)
 190             throw newNoAccessException(method, caller);
 191         return bmh;
 192     }
 193 
 194     /**
 195      * Make a direct method handle to <i>m</i>, if the current caller has permission.
 196      * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
 197      * If <i>m</i> is virtual, overriding is respected on every call.
 198      * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
 199      * The type of the method handle will be that of the method,
 200      * with the receiver type prepended (but only if it is non-static).
 201      * If the method's {@code accessible} flag is not set,
 202      * access checking is performed immediately on behalf of the caller.
 203      * If <i>m</i> is not public, do not share the resulting handle with untrusted callers.
 204      * @param m the reflected method
 205      * @return a method handle which can invoke the reflected method
 206      * @exception NoAccessException if access checking fails
 207      */
 208     public static
 209     MethodHandle unreflect(Method m) throws NoAccessException {
 210         Class<?> caller = Reflection.getCallerClass(2);
 211         return unreflect(new MemberName(m), m.isAccessible(), true, caller);
 212     }
 213 
 214     /**
 215      * Produce a method handle for a reflected method.
 216      * It will bypass checks for overriding methods on the receiver,
 217      * as if by the {@code invokespecial} instruction.
 218      * The type of the method handle will be that of the method,
 219      * with the receiver type prepended.
 220      * If the method's {@code accessible} flag is not set,
 221      * access checking is performed immediately on behalf of the caller,
 222      * as if {@code invokespecial} instruction were being linked.
 223      * @param m the reflected method
 224      * @return a method handle which can invoke the reflected method
 225      * @exception NoAccessException if access checking fails
 226      */
 227     public static
 228     MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
 229         Class<?> caller = Reflection.getCallerClass(2);
 230         checkSpecialCaller(specialCaller, caller);
 231         MemberName mname = new MemberName(m);
 232         checkStatic(false, mname, caller);
 233         return unreflect(mname, m.isAccessible(), false, specialCaller);
 234     }
 235 
 236 //    /**
 237 //     * Produce a method handle for a reflected constructor.
 238 //     * It will allow direct access to the constructor,
 239 //     * as if by the {@code invokespecial} instruction.
 240 //     * The type of the method handle will be that of the method,
 241 //     * with the receiver type prepended.
 242 //     * If the constructor's {@code accessible} flag is not set,
 243 //     * access checking is performed immediately on behalf of the caller,
 244 //     * as if {@code invokespecial} instruction were being linked.
 245 //     * @param ctor the reflected constructor
 246 //     * @param specialCaller the proposed calling class to perform the {@code invokespecial}
 247 //     * @return a method handle which can invoke the reflected constructor
 248 //     * @exception NoAccessException if access checking fails
 249 //     */
 250 //    public static
 251 //    MethodHandle unreflectSpecial(Constructor ctor, Class<?> specialCaller) throws NoAccessException {
 252 //        Class<?> caller = Reflection.getCallerClass(2);
 253 //        checkSpecialCaller(specialCaller, caller);
 254 //        MemberName m = new MemberName(ctor);
 255 //        checkStatic(false, m, caller);
 256 //        return unreflect(m, ctor.isAccessible(), false, specialCaller);
 257 //    }
 258 
 259     private static
 260     void checkSpecialCaller(Class<?> specialCaller, Class<?> caller) {
 261         if (caller != null && !VerifyAccess.isSamePackageMember(specialCaller, caller))
 262             throw newNoAccessException("no private access", new MemberName(specialCaller), caller);
 263     }
 264 
 265     // Helper for creating handles on reflected methods and constructors.
 266     private static
 267     MethodHandle unreflect(MemberName m, boolean isAccessible, boolean doDispatch, Class<?> caller) {
 268         MethodType mtype = m.getInvocationType();
 269         Class<?> defc = m.getDeclaringClass();
 270         int mods = m.getModifiers();
 271         if (m.isStatic()) {
 272             if (!isAccessible &&
 273                     VerifyAccess.isAccessible(defc, mods, false, caller) == null)
 274                 throw newNoAccessException(m, caller);
 275         } else {
 276             Class<?> constraint;
 277             if (isAccessible) {
 278                 // abbreviated access check for "unlocked" method
 279                 constraint = doDispatch ? defc : caller;
 280             } else {
 281                 constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, caller);
 282             }
 283             if (constraint != defc && !constraint.isAssignableFrom(defc)) {
 284                 if (!defc.isAssignableFrom(constraint))
 285                     throw newNoAccessException("receiver must be in caller class", m, caller);
 286                 mtype = mtype.changeParameterType(0, constraint);
 287             }
 288         }
 289         return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, caller);
 290     }
 291 
 292     /**
 293      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 294      * Produce a method handle giving read access to a reflected field.
 295      * The type of the method handle will have a return type of the field's
 296      * value type.  Its sole argument will be the field's containing class
 297      * (but only if it is non-static).
 298      * If the method's {@code accessible} flag is not set,
 299      * access checking is performed immediately on behalf of the caller.
 300      * @param f the reflected field
 301      * @return a method handle which can load values from the reflected field
 302      * @exception NoAccessException if access checking fails
 303      */
 304     public static
 305     MethodHandle unreflectGetter(Field f) throws NoAccessException {
 306         Class<?> caller = Reflection.getCallerClass(2);
 307         return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, (Class)caller);
 308     }
 309 
 310     /**
 311      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 312      * Produce a method handle giving write access to a reflected field.
 313      * The type of the method handle will have a void return type.
 314      * Its last argument will be the field's value type.
 315      * Its other argument will be the field's containing class
 316      * (but only if it is non-static).
 317      * If the method's {@code accessible} flag is not set,
 318      * access checking is performed immediately on behalf of the caller.
 319      * @param f the reflected field
 320      * @return a method handle which can store values into the reflected field
 321      * @exception NoAccessException if access checking fails
 322      */
 323     public static
 324     MethodHandle unreflectSetter(Field f) throws NoAccessException {
 325         Class<?> caller = Reflection.getCallerClass(2);
 326         return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, (Class)caller);
 327     }
 328 
 329     /**
 330      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 331      * Produce a method handle giving read access to elements of an array.
 332      * The type of the method handle will have a return type of the array's
 333      * element type.  Its first argument will be the array type,
 334      * and the second will be {@code int}.
 335      * @param arrayClass an array type
 336      * @return a method handle which can load values from the given array type
 337      * @throws  IllegalArgumentException if arrayClass is not an array type
 338      */
 339     public static
 340     MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
 341         Class<?> caller = Reflection.getCallerClass(2);
 342         return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false, (Class)caller);
 343     }
 344 
 345     /**
 346      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 347      * Produce a method handle giving write access to elements of an array.
 348      * The type of the method handle will have a void return type.
 349      * Its last argument will be the array's element type.
 350      * The first and second arguments will be the array type and int.
 351      * @return a method handle which can store values into the array type
 352      * @throws IllegalArgumentException if arrayClass is not an array type
 353      */
 354     public static
 355     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
 356         Class<?> caller = Reflection.getCallerClass(2);
 357         return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true, (Class)caller);
 358     }
 359 
 360 
 361     /// method handle invocation (reflective style)
 362 
 363     /**
 364      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 365      * Call the {@code invoke} method of a given method handle.
 366      * The given arguments must exactly match the parameter types of the method handle.
 367      * <em>TBD: Fill in the details.</em>
 368      * No conversions are performed except reference casting and unboxing of primitives.
 369      * @param target method handle to invoke
 370      * @param arguments arguments to pass to the target (with any primitives wrapped)
 371      * @return the result of the method (with any primitive wrapped)
 372      */
 373     public static
 374     Object invoke(MethodHandle target, Object... arguments) {
 375         // TO DO: Remove this checking logic; must be part of the invoker anyway.
 376         int length = arguments.length;
 377         MethodType type = target.type();
 378         if (type.parameterCount() != length)
 379             throw new WrongMethodTypeException("wrong number of arguments");
 380         for (int i = 0; i < length; i++) {
 381             Object argument = arguments[i];
 382             Class<?> ptype = type.parameterType(i);
 383             if (ptype.isPrimitive()) {
 384                 argument.getClass();  // provoke NPE if null
 385                 ptype = Wrappers.asWrapperType(ptype);
 386             } else if (ptype.isInterface()) {
 387                 ptype = Object.class;   // no check
 388             }
 389             if (ptype != Object.class) {
 390                 ptype.cast(argument);
 391             }
 392         }
 393         // End of checking logic.
 394         return MethodHandleInvoker.make(target.type()).invoke(target, arguments);
 395     }
 396 
 397     /**
 398      * <em>WORK IN PROGRESS:</em>
 399      * Perform value checking, exactly as if for an adapted method handle.
 400      * It is assumed that the given value is either null, of type T0,
 401      * or (if T0 is primitive) of the wrapper type corresponding to T0.
 402      * The following checks and conversions are made:
 403      * <ul>
 404      * <li>If T0 and T1 are references, then a cast to T1 is applied.
 405      *     (The types do not need to be related in any particular way.)
 406      * <li>If T0 and T1 are primitives, then a widening or narrowing
 407      *     conversion is applied, if one exists.
 408      * <li>If T0 is a primitive and T1 a reference, and
 409      *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
 410      *     possibly followed by a reference conversion.
 411      *     T1 must be TW or a supertype.
 412      * <li>If T0 is a reference and T1 a primitive, and
 413      *     T1 has a wrapper type TW, an unboxing conversion is applied,
 414      *     possibly preceded by a reference conversion.
 415      *     T0 must be TW or a supertype.
 416      * <li>If T1 is void, the return value is discarded
 417      * <li>If T0 is void and T1 a reference, a null value is introduced.
 418      * <li>If T0 is void and T1 a primitive, a zero value is introduced.
 419      * </ul>
 420      * If the value is discarded, null will be returned.
 421      * @param valueType
 422      * @param value
 423      * @return the value, converted if necessary
 424      * @throws java.lang.ClassCastException if a cast fails
 425      */
 426     static
 427     Object checkValue(Class<?> T0, Class<?> T1, Object value)
 428        throws ClassCastException
 429     {
 430         if (T0 == T1) {
 431             // no conversion needed
 432             return value;
 433         }
 434         boolean prim0 = T0.isPrimitive(), prim1 = T1.isPrimitive();
 435         Class<?> TW;
 436         if (!prim0) {
 437             if (!prim1) {
 438                 return T1.cast(T0.cast(value));
 439             }
 440             // convert reference to primitive by unboxing
 441             TW = Wrappers.asWrapperType(T0);
 442             return T1.cast(TW.cast(value));
 443         }
 444         if (!prim1) {
 445             // convert primitive to reference type by boxing
 446             TW = Wrappers.asWrapperType(T1);
 447             return TW.cast(T0.cast(value));
 448         }
 449         // convert primitive to primitive; this requires a real value change
 450         if (value == null)
 451             return Wrappers.zeroValue(T1);
 452         // convert non-Number primitives to Integer:
 453         if (value instanceof Character) {
 454             char ch = (char) (Character) value;
 455             value = Integer.valueOf(ch);
 456             if (T1 == Integer.class)
 457                 return value;
 458         } else if (value instanceof Boolean) {
 459             boolean z = (boolean) (Boolean) value;
 460             value = Integer.valueOf(z ? 1 : 0);
 461             if (T1 == Integer.class)
 462                 return value;
 463         }
 464         Number numval = (Number) value;
 465         switch (Wrappers.basicTypeChar(T1)) {
 466         case 'Z': return (numval.intValue() != 0);
 467         case 'B': return numval.byteValue();
 468         case 'C': return (char) numval.intValue();
 469         case 'S': return numval.shortValue();
 470         case 'I': return numval.intValue();
 471         case 'J': return numval.longValue();
 472         case 'F': return numval.floatValue();
 473         case 'D': return numval.doubleValue();
 474         }
 475         return null;
 476     }
 477 
 478     static
 479     Object checkValue(Class<?> T1, Object value)
 480        throws ClassCastException
 481     {
 482         Class<?> T0;
 483         if (value == null)
 484             T0 = Object.class;
 485         else
 486             T0 = value.getClass();
 487         return checkValue(T0, T1, value);
 488     }
 489 
 490     /// method handle modification (creation from other method handles)
 491 
 492     /**
 493      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 494      * Produce a method handle which adapts the type of the
 495      * given method handle to a new type, by pairwise argument conversion,
 496      * and/or varargs conversion.
 497      * The original type and new type must have the same number of
 498      * arguments, or else one or both them the must be varargs types.
 499      * The resulting method handle is guaranteed to confess a type
 500      * which is equal to the desired new type, with any varargs property erased.
 501      * <p>
 502      * If the original type and new type are equal, returns target.
 503      * <p>
 504      * The following conversions are applied as needed both to
 505      * arguments and return types.  Let T0 and T1 be the differing
 506      * new and old parameter types (or old and new return types)
 507      * for corresponding values passed by the new and old method types.
 508      * <p>
 509      * If an ordinary (non-varargs) parameter of the new type is
 510      * to be boxed in a varargs parameter of the old type of type T1[],
 511      * then T1 is the element type of the varargs array.
 512      * Otherwise, if a varargs parameter of the new type of type T0[]
 513      * is to be spread into one or more outgoing old type parameters,
 514      * then T0 is the element type of the
 515      * If the new type is varargs and the old type is not, the varargs
 516      * argument will be checked and must be a non-null array of exactly
 517      * the right length.  If there are no parameters in the old type
 518      * corresponding to the new varargs parameter, the varargs argument
 519      * is also allowed to be null.
 520      * <p>
 521      * Given those types T0, T1, one of the following conversions is applied
 522      * if possible:
 523      * <ul>
 524      * <li>If T0 and T1 are references, then a cast to T2 is applied,
 525      *     where T2 is Object if T1 is an interface, else T1.
 526      *     (The types do not need to be related in any particular way.
 527      *     The treatment of interfaces follows the usage of the bytecode verifier.)
 528      * <li>If T0 and T1 are primitives, then a Java casting
 529      *     conversion (JLS 5.5) is applied, if one exists.
 530      * <li>If T0 and T1 are primitives and one is boolean,
 531      *     the boolean is treated as a one-bit unsigned integer.
 532      *     (This treatment follows the usage of the bytecode verifier.)
 533      *     A conversion from another primitive type behaves as if
 534      *     it first converts to byte, and then masks all but the low bit.
 535      * <li>If T0 is a primitive and T1 a reference, a boxing
 536      *     conversion is applied if one exists, possibly followed by
 537      *     an reference conversion to a superclass.
 538      *     T1 must be a wrapper class or a supertype of one.
 539      *     If T1 is a wrapper class, T0 is converted if necessary
 540      *     to T1's primitive type by one of the preceding conversions.
 541      *     Otherwise, T0 is boxed, and its wrapper converted to T1.
 542      * <li>If T0 is a reference and T1 a primitive, an unboxing
 543      *     conversion is applied if one exists, possibly preceded by
 544      *     a reference conversion to a wrapper class.
 545      *     T0 must be a wrapper class or a supertype of one.
 546      *     If T0 is a wrapper class, its primitive value is converted
 547      *     if necessary to T1 by one of the preceding conversions.
 548      *     Otherwise, T0 is converted directly to the wrapper type for T1,
 549      *     which is then unboxed.
 550      * <li>If T1 is void, any returned value is discarded
 551      * <li>If T0 is void and T1 a reference, a null value is introduced.
 552      * <li>If T0 is void and T1 a primitive, a zero value is introduced.
 553      * </ul>
 554      * @param target the method handle to invoke after arguments are retyped
 555      * @param newType the expected type of the new method handle
 556      * @return a method handle which delegates to {@code target} after performing
 557      *           any necessary argument conversions, and arranges for any
 558      *           necessary return value conversions
 559      */
 560     public static
 561     MethodHandle convertArguments(MethodHandle target, MethodType newType) {
 562         MethodType oldType = target.type();
 563         if (oldType.equals(newType))
 564             return target;
 565         return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
 566                                                  newType, target.type(), null);
 567     }
 568 
 569     /**
 570      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 571      * Produce a method handle which adapts the calling sequence of the
 572      * given method handle to a new type, by reordering the arguments.
 573      * Duplication and omission is allowed.
 574      * The resulting method handle is guaranteed to confess a type
 575      * which is equal to the desired new type.
 576      * <p>
 577      * The given permutation string controls the reordering.
 578      * The characters of the string are treated as small integers.
 579      * All the characters must be in the range zero (i.e., '\0') to
 580      * the number of incoming arguments (the parameter count of the new type).
 581      * The length of the string must be equal to the number of outgoing
 582      * parameters (the parameter count of the original method handle's type).
 583      * If the n-th character of the string denotes the integer k,
 584      * then the n-th incoming argument becomes the k-th outgoing argument.
 585      * <p>
 586      * Pairwise conversions are applied as needed to arguments and return
 587      * values, as with {@link #convertArguments}.
 588      * @param target the method handle to invoke after arguments are reordered
 589      * @param newType the expected type of the new method handle
 590      * @param permutation a string which controls the reordering
 591      * @return a method handle which delegates to {@code target} after performing
 592      *           any necessary argument motion and conversions, and arranges for any
 593      *           necessary return value conversions
 594      */
 595     public static
 596     MethodHandle permuteArguments(MethodHandle target, MethodType newType, String permutation) {
 597         MethodType oldType = target.type();
 598         return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
 599                                                  newType, target.type(),
 600                                                  permutation);
 601     }
 602 
 603     /**
 604      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 605      * Produce a method handle which adapts the type of the
 606      * given method handle to a new type, by spreading the final argument.
 607      * The resulting method handle is guaranteed to confess a type
 608      * which is equal to the desired new type.
 609      * <p>
 610      * The final parameter type of the new type must be an array type T[].
 611      * This is the type of what is called the <i>spread</i> argument.
 612      * All other arguments of the new type are called <i>ordinary</i> arguments.
 613      * <p>
 614      * The ordinary arguments of the new type are pairwise converted
 615      * to the initial parameter types of the old type, according to the
 616      * rules in {@link #convertArguments}.
 617      * Any additional arguments in the old type
 618      * are converted from the array element type T,
 619      * again according to the rules in {@link #convertArguments}.
 620      * The return value is converted according likewise.
 621      * <p>
 622      * The call verifies that the spread argument is in fact an array
 623      * of exactly the type length, i.e., the excess number of
 624      * arguments in the old type over the ordinary arguments in the new type.
 625      * If there are no excess arguments, the spread argument is also
 626      * allowed to be null.
 627      * @param target the method handle to invoke after the argument is prepended
 628      * @param newType the expected type of the new method handle
 629      * @return a new method handle which spreads its final argument,
 630      *         before calling the original method handle
 631      */
 632     public static
 633     MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
 634         MethodType oldType = target.type();
 635         int inargs  = newType.parameterCount();
 636         int outargs = oldType.parameterCount();
 637         int spreadPos = inargs - 1;
 638         int numSpread = (outargs - spreadPos);
 639         if (spreadPos < 0 || numSpread < 0)
 640             throw newIllegalArgumentException("wrong number of arguments");
 641         newType = newType.changeVarArgs(true);
 642         return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
 643     }
 644 
 645     /**
 646      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 647      * Produce a method handle which adapts the type of the
 648      * given method handle to a new type, by collecting a series of
 649      * trailing arguments into an array.
 650      * The resulting method handle is guaranteed to confess a type
 651      * which is equal to the desired new type.
 652      * <p>
 653      * This method is inverse to {@link #spreadArguments}.
 654      * The final parameter type of the old type must be an array type T[],
 655      * which is the type of what is called the <i>spread</i> argument.
 656      * The trailing arguments of the new type which correspond to
 657      * the spread argument are all converted to type T and collected
 658      * into an array before the original method is called.
 659      * @param target the method handle to invoke after the argument is prepended
 660      * @param newType the expected type of the new method handle
 661      * @return a new method handle which collects some trailings argument
 662      *         into an array, before calling the original method handle
 663      */
 664     public static
 665     MethodHandle collectArguments(MethodHandle target, MethodType newType) {
 666         MethodType oldType = target.type();
 667         int inargs  = newType.parameterCount();
 668         int outargs = oldType.parameterCount();
 669         int collectPos = outargs - 1;
 670         int numCollect = (inargs - collectPos);
 671         if (collectPos < 0 || numCollect < 0)
 672             throw newIllegalArgumentException("wrong number of arguments");
 673         oldType = oldType.changeVarArgs(true);
 674         return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
 675     }
 676 
 677     /**
 678      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 679      * Produce a method handle which calls the original method handle,
 680      * after inserting the given argument as the first argument.
 681      * The type of the new method handle will drop the first argument
 682      * type from the original handle's type.
 683      * <p>
 684      * Equivalent to {@code insertArgument(target, value, 0)}.
 685      */
 686     public static
 687     MethodHandle insertArgument(MethodHandle target, Object value) {
 688         return insertArgument(target, value, 0);
 689     }
 690 
 691     /**
 692      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 693      * Produce a method handle which calls the original method handle,
 694      * after appending the given argument as the final argument.
 695      * The type of the new method handle will drop the last argument
 696      * type from the original handle's type.
 697      * <p>
 698      * Equivalent to {@code insertArgument(target, value, N)},
 699      * where <i>N</i> is the number of arguments to <i>target</i>.
 700      */
 701     public static
 702     MethodHandle appendArgument(MethodHandle target, Object value) {
 703         return insertArgument(target, value, target.type().parameterCount());
 704     }
 705 
 706     /**
 707      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 708      * Produce a method handle which calls the original method handle,
 709      * after inserting the given argument at the given position.
 710      * The type of the new method handle will drop the corresponding argument
 711      * type from the original handle's type.
 712      * <p>
 713      * The given argument object must match the dropped argument type.
 714      * If the dropped argument type is a primitive, the argument object
 715      * must be a wrapper, and is unboxed to produce the primitive.
 716      * <p>
 717      * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
 718      * where <i>N</i> is the number of argument types in <i>target</i>,
 719      * meaning to insert the new argument as the first or last (respectively),
 720      * or somewhere in between.
 721      * @param target the method handle to invoke after the argument is inserted
 722      * @param value the argument to insert
 723      * @param pos where to insert the argument (zero for the first)
 724      * @return a new method handle which inserts an additional argument,
 725      *         before calling the original method handle
 726      */
 727     public static
 728     MethodHandle insertArgument(MethodHandle target, Object value, int pos) {
 729         MethodType oldType = target.type();
 730         ArrayList<Class<?>> ptypes =
 731                 new ArrayList<Class<?>>(oldType.parameterList());
 732         int outargs = oldType.parameterCount();
 733         int inargs  = outargs - 1;
 734         if (pos < 0 || pos >= outargs)
 735             throw newIllegalArgumentException("no argument type to append");
 736         Class<?> valueType = ptypes.remove(pos);
 737         value = checkValue(valueType, value);
 738         if (pos == 0 && !valueType.isPrimitive()) {
 739             // At least for now, make bound method handles a special case.
 740             // This lets us get by with minimal JVM support, at the expense
 741             // of generating signature-specific adapters as Java bytecodes.
 742             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
 743             if (bmh != null)  return bmh;
 744             // else fall through to general adapter machinery
 745         }
 746         return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
 747     }
 748 
 749     /**
 750      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 751      * Produce a method handle which calls the original method handle,
 752      * after dropping the given argument(s) at the given position.
 753      * The type of the new method handle will insert the given argument
 754      * type(s), at that position, into the original handle's type.
 755      * <p>
 756      * The <i>pos</i> may range between zero and <i>N-1</i>,
 757      * where <i>N</i> is the number of argument types in <i>target</i>,
 758      * meaning to drop the first or last argument (respectively),
 759      * or an argument somewhere in between.
 760      * @param target the method handle to invoke after the argument is dropped
 761      * @param valueTypes the type(s) of the argument to drop
 762      * @param pos which argument to drop (zero for the first)
 763      * @return a new method handle which drops an argument of the given type,
 764      *         before calling the original method handle
 765      */
 766     public static
 767     MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
 768         if (valueTypes.length == 0)  return target;
 769         MethodType oldType = target.type();
 770         int outargs = oldType.parameterCount();
 771         int inargs  = outargs + valueTypes.length;
 772         if (pos < 0 || pos >= inargs)
 773             throw newIllegalArgumentException("no argument type to remove");
 774         ArrayList<Class<?>> ptypes =
 775                 new ArrayList<Class<?>>(oldType.parameterList());
 776         ptypes.addAll(pos, Arrays.asList(valueTypes));
 777         MethodType newType = MethodType.make(oldType.returnType(), ptypes);
 778         return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
 779     }
 780 
 781     /**
 782      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 783      * Make a method handle which adapts a target method handle,
 784      * by guarding it with a test, a boolean-valued method handle.
 785      * If the guard fails, a fallback handle is called instead.
 786      * All three method handles must have the same corresponding
 787      * argument and return types, except that the return type
 788      * of the test must be boolean.
 789      * <p> Here is pseudocode for the resulting adapter:
 790      * <blockquote><pre>
 791      * signature T(A...);
 792      * boolean test(A...);
 793      * T target(A...);
 794      * T fallback(A...);
 795      * T adapter(A... a) {
 796      *   if (test(a...))
 797      *     return target(a...);
 798      *   else
 799      *     return fallback(a...);
 800      * }
 801      * </pre></blockquote>
 802      * @param test method handle used for test, must return boolean
 803      * @param target method handle to call if test passes
 804      * @param fallback method handle to call if test fails
 805      * @return method handle which incorporates the specified if/then/else logic
 806      * @throws IllegalArgumentException if {@code test} does not return boolean,
 807      *          or if all three method types do not match (with the return
 808      *          type of {@code test} changed to match that of {@code target}).
 809      */
 810     public static
 811     MethodHandle guardWithTest(MethodHandle test,
 812                                MethodHandle target,
 813                                MethodHandle fallback) {
 814         if (target.type() != fallback.type())
 815             throw newIllegalArgumentException("target and fallback types do not match");
 816         if (target.type().changeReturnType(boolean.class) != test.type())
 817             throw newIllegalArgumentException("target and test types do not match");
 818         /* {
 819             MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
 820                 return z ? t : f;
 821             }
 822             MethodHandle choose = findVirtual(MethodHandles.class, "choose",
 823                     MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
 824             choose = appendArgument(choose, target);
 825             choose = appendArgument(choose, fallback);
 826             choose = combineArguments(choose, test);
 827             MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
 828             return checkArguments(invoke, choose, 0);
 829         } */
 830         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
 831     }
 832 
 833     /**
 834      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 835      * Adapt a target method handle {@code target} by first checking its arguments,
 836      * and then calling the target.
 837      * The check is performed by a second method handle, the {@code checker}.
 838      * After this, control passes to the target method handle, with the same
 839      * arguments.
 840      * <p>
 841      * The return value of the checker is inserted into the argument list
 842      * for {@code target} at the indicated position {@code pos}, if it is non-negative.
 843      * Except for this inserted argument (if any), the argument types of
 844      * the target {@code target} and the {@code checker} must be identical.
 845      * <p>
 846      * The checker handle must have the same argument types as the
 847      * target handle, but must return {@link MethodHandle} instead of
 848      * the ultimate return type.  The returned method handle, in turn,
 849      * is required to have exactly the given final method type.
 850      * <p> Here is pseudocode for the resulting adapter:
 851      * <blockquote><pre>
 852      * signature V(A[pos]..., B...);
 853      * signature T(A[pos]..., V, B...);
 854      * T target(A... a, V, B... b);
 855      * U checker(A..., B...);
 856      * T adapter(A... a, B... b) {
 857      *   V v = checker(a..., b...);
 858      *   return target(a..., v, b...);
 859      * }
 860      * </pre></blockquote>
 861      * @param target the method handle to invoke after arguments are checked
 862      * @param checker method handle to call initially on the incoming arguments
 863      * @param pos where the return value of {@code checker} is to
 864      *          be inserted as an argument to {@code target}
 865      * @return method handle which incorporates the specified dispatch logic
 866      * @throws IllegalArgumentException if {@code checker} does not itself
 867      *          return either void or the {@code pos}-th argument of {@code target},
 868      *          or does not have the same argument types as {@code target}
 869      *          (minus the inserted argument)
 870      */
 871     public static
 872     MethodHandle checkArguments(MethodHandle target, MethodHandle checker, int pos) {
 873         MethodType mhType = target.type();
 874         Class<?> checkType = checker.type().returnType();
 875         MethodType incomingArgs;
 876         if (pos < 0) {
 877             // No inserted argument; target & checker must have same argument types.
 878             incomingArgs = mhType;
 879             if (!incomingArgs.changeReturnType(checkType).equals(checker.type()))
 880                 throw newIllegalArgumentException("target and checker types do not match");
 881         } else {
 882             // Inserted argument.
 883             if (pos >= mhType.parameterCount()
 884                 || mhType.parameterType(pos) != checkType)
 885                 throw newIllegalArgumentException("inserted checker argument does not match target");
 886             incomingArgs = mhType.deleteParameterType(pos);
 887         }
 888         if (!incomingArgs.changeReturnType(checkType).equals(checker.type())) {
 889             throw newIllegalArgumentException("target and checker types do not match");
 890         }
 891         return MethodHandleImpl.checkArguments(IMPL_TOKEN, target, checker, pos);
 892     }
 893 
 894     /// standard method handles
 895 
 896     /**
 897      * Identity function.
 898      * @param x an arbitrary reference value
 899      * @return the same value x
 900      */
 901     /*public*/ static <T>
 902     T identity(T x) {
 903         return x;
 904     }
 905 
 906     /**
 907      * A method handle for {@link #identity}
 908      */
 909     /*public*/ static
 910     MethodHandle identityMethod() {
 911         if (IDENTITY == null)
 912             IDENTITY = findStatic(MethodHandle.class, "identity", IDENTITY_TYPE);
 913         return IDENTITY;
 914     }
 915     private static
 916     MethodHandle IDENTITY;
 917     private static final
 918     MethodType IDENTITY_TYPE = MethodType.make(Object.class, Object.class);
 919 
 920     /**
 921      * Empty function.
 922      */
 923     /*public*/ static
 924     void empty() {
 925     }
 926 
 927     /**
 928      * A method handle for {@link #empty}
 929      */
 930     /*public*/ static
 931     MethodHandle emptyMethod() {
 932         if (EMPTY == null)
 933             EMPTY = findStatic(MethodHandle.class, "empty", EMPTY_TYPE);
 934         return EMPTY;
 935     }
 936     private static
 937     MethodHandle EMPTY;
 938     private static final
 939     MethodType EMPTY_TYPE = MethodType.make(void.class);
 940 }