jdk/src/share/classes/java/dyn/MethodHandles.java
changeset 5725 16c1792b2ee6
parent 5506 202f599c92aa
parent 5722 4ada807383c8
child 5727 f825b9b605e4
equal deleted inserted replaced
5721:faedb20bdcbb 5725:16c1792b2ee6
     1 /*
     1 /*
     2  * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    42 import sun.reflect.Reflection;
    42 import sun.reflect.Reflection;
    43 import static sun.dyn.MemberName.newIllegalArgumentException;
    43 import static sun.dyn.MemberName.newIllegalArgumentException;
    44 import static sun.dyn.MemberName.newNoAccessException;
    44 import static sun.dyn.MemberName.newNoAccessException;
    45 
    45 
    46 /**
    46 /**
    47  * Fundamental operations and utilities for MethodHandle.
    47  * This class consists exclusively of static methods that operate on or return
    48  * They fall into several categories:
    48  * method handles. They fall into several categories:
    49  * <ul>
    49  * <ul>
    50  * <li>Reifying methods and fields.  This is subject to access checks.
    50  * <li>Factory methods which create method handles for methods and fields.
    51  * <li>Invoking method handles on dynamically typed arguments and/or varargs arrays.
    51  * <li>Invoker methods which can invoke method handles on dynamically typed arguments and/or varargs arrays.
    52  * <li>Combining or transforming pre-existing method handles into new ones.
    52  * <li>Combinator methods, which combine or transforming pre-existing method handles into new ones.
    53  * <li>Miscellaneous emulation of common JVM operations or control flow patterns.
    53  * <li>Factory methods which create method handles that emulate other common JVM operations or control flow patterns.
    54  * </ul>
    54  * </ul>
    55  * <p>
    55  * <p>
    56  * @author John Rose, JSR 292 EG
    56  * @author John Rose, JSR 292 EG
    57  */
    57  */
    58 public class MethodHandles {
    58 public class MethodHandles {
    64     static { MethodHandleImpl.initStatics(); }
    64     static { MethodHandleImpl.initStatics(); }
    65     // See IMPL_LOOKUP below.
    65     // See IMPL_LOOKUP below.
    66 
    66 
    67     //// Method handle creation from ordinary methods.
    67     //// Method handle creation from ordinary methods.
    68 
    68 
    69     /** Create a {@link Lookup} lookup object on the caller.
    69     /**
    70      *
    70      * Return a {@link Lookup lookup object} on the caller,
       
    71      * which has the capability to access any method handle that the caller has access to,
       
    72      * including direct method handles to private fields and methods.
       
    73      * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
       
    74      * Do not store it in place where untrusted code can access it.
    71      */
    75      */
    72     public static Lookup lookup() {
    76     public static Lookup lookup() {
    73         return new Lookup();
    77         return new Lookup();
    74     }
    78     }
    75 
    79 
    76     /** Version of lookup which is trusted minimally.
    80     /**
    77      *  It can only be used to create method handles to
    81      * Return a {@link Lookup lookup object} which is trusted minimally.
    78      *  publicly accessible members.
    82      * It can only be used to create method handles to
       
    83      * publicly accessible fields and methods.
    79      */
    84      */
    80     public static Lookup publicLookup() {
    85     public static Lookup publicLookup() {
    81         return Lookup.PUBLIC_LOOKUP;
    86         return Lookup.PUBLIC_LOOKUP;
    82     }
    87     }
    83 
    88 
    84     /**
    89     /**
    85      * A factory object for creating method handles, when the creation
    90      * A <em>lookup object</em> is a factory for creating method handles,
    86      * requires access checking.  Method handles do not perform
    91      * when the creation requires access checking.
       
    92      * Method handles do not perform
    87      * access checks when they are called; this is a major difference
    93      * access checks when they are called; this is a major difference
    88      * from reflective {@link Method}, which performs access checking
    94      * from reflective {@link Method}, which performs access checking
    89      * against every caller, on every call.  Method handle access
    95      * against every caller, on every call.
    90      * restrictions are enforced when a method handle is created.
    96      * Therefore, method handle access
       
    97      * restrictions must be enforced when a method handle is created.
    91      * The caller class against which those restrictions are enforced
    98      * The caller class against which those restrictions are enforced
    92      * is known as the "lookup class".  {@link Lookup} embodies an
    99      * is known as the {@linkplain #lookupClass lookup class}.
       
   100      * A lookup object embodies an
    93      * authenticated lookup class, and can be used to create any number
   101      * authenticated lookup class, and can be used to create any number
    94      * of access-checked method handles, all checked against a single
   102      * of access-checked method handles, all checked against a single
    95      * lookup class.
   103      * lookup class.
    96      * <p>
   104      * <p>
    97      * A class which needs to create method handles will call
   105      * A class which needs to create method handles will call
    98      * {@code MethodHandles.lookup()} to create a factory for itself.
   106      * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
    99      * It may then use this factory to create method handles on
   107      * It may then use this factory to create method handles on
   100      * all of its methods, including private ones.
   108      * all of its methods, including private ones.
   101      * It may also delegate the lookup (e.g., to a metaobject protocol)
   109      * It may also delegate the lookup (e.g., to a metaobject protocol)
   102      * by passing the {@code Lookup} object to other code.
   110      * by passing the {@code Lookup} object to other code.
   103      * If this other code creates method handles, they will be access
   111      * If this other code creates method handles, they will be access
   104      * checked against the original lookup class, and not with any higher
   112      * checked against the original lookup class, and not with any higher
   105      * privileges.
   113      * privileges.
   106      * <p>
   114      * <p>
   107      * Note that access checks only apply to named and reflected methods.
   115      * Access checks only apply to named and reflected methods.
   108      * Other method handle creation methods, such as {@link #convertArguments},
   116      * Other method handle creation methods, such as
       
   117      * {@link #convertArguments MethodHandles.convertArguments},
   109      * do not require any access checks, and can be done independently
   118      * do not require any access checks, and can be done independently
   110      * of any lookup class.
   119      * of any lookup class.
   111      * <p>
   120      * <h3>How access errors are handled</h3>
   112      * <em>A note about error conditions:<em>  A lookup can fail, because
   121      * A lookup can fail, because
   113      * the containing class is not accessible to the lookup class, or
   122      * the containing class is not accessible to the lookup class, or
   114      * because the desired class member is missing, or because the
   123      * because the desired class member is missing, or because the
   115      * desired class member is not accessible to the lookup class.
   124      * desired class member is not accessible to the lookup class.
   116      * It can also fail if a security manager is installed and refuses
   125      * It can also fail if a security manager is installed and refuses
   117      * access.  In any of these cases, an exception will be
   126      * access.  In any of these cases, an exception will be
   122      * At least some of these error conditions are likely to be
   131      * At least some of these error conditions are likely to be
   123      * represented by checked exceptions in the final version of this API.
   132      * represented by checked exceptions in the final version of this API.
   124      */
   133      */
   125     public static final
   134     public static final
   126     class Lookup {
   135     class Lookup {
       
   136         /** The class on behalf of whom the lookup is being performed. */
   127         private final Class<?> lookupClass;
   137         private final Class<?> lookupClass;
       
   138 
       
   139         /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
       
   140         private final int allowedModes;
       
   141 
       
   142         private static final int
       
   143             PUBLIC    = Modifier.PUBLIC,
       
   144             PACKAGE   = Modifier.STRICT,
       
   145             PROTECTED = Modifier.PROTECTED,
       
   146             PRIVATE   = Modifier.PRIVATE,
       
   147             ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
       
   148             TRUSTED   = -1;
       
   149 
       
   150         private static int fixmods(int mods) {
       
   151             mods &= (ALL_MODES - PACKAGE);
       
   152             return (mods != 0) ? mods : PACKAGE;
       
   153         }
   128 
   154 
   129         /** Which class is performing the lookup?  It is this class against
   155         /** Which class is performing the lookup?  It is this class against
   130          *  which checks are performed for visibility and access permissions.
   156          *  which checks are performed for visibility and access permissions.
   131          *  <p>
   157          *  <p>
   132          *  This value is null if and only if this lookup was produced
   158          *  This value is null if and only if this lookup was produced
   134          */
   160          */
   135         public Class<?> lookupClass() {
   161         public Class<?> lookupClass() {
   136             return lookupClass;
   162             return lookupClass;
   137         }
   163         }
   138 
   164 
       
   165         // This is just for calling out to MethodHandleImpl.
       
   166         private Class<?> lookupClassOrNull() {
       
   167             return (allowedModes == TRUSTED) ? null : lookupClass;
       
   168         }
       
   169 
       
   170         /** Which types of members can this lookup object produce?
       
   171          *  The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
       
   172          *  The modifier bit STRICT stands in for the (non-existent) package protection mode.
       
   173          */
       
   174         int lookupModes() {
       
   175             return allowedModes & ALL_MODES;
       
   176         }
       
   177 
   139         /** Embody the current class (the lookupClass) as a lookup class
   178         /** Embody the current class (the lookupClass) as a lookup class
   140          * for method handle creation.
   179          * for method handle creation.
   141          * Must be called by from a method in this package,
   180          * Must be called by from a method in this package,
   142          * which in turn is called by a method not in this package.
   181          * which in turn is called by a method not in this package.
       
   182          * <p>
   143          * Also, don't make it private, lest javac interpose
   183          * Also, don't make it private, lest javac interpose
   144          * an access$N method.
   184          * an access$N method.
   145          */
   185          */
   146         Lookup() {
   186         Lookup() {
   147             this(IMPL_TOKEN, getCallerClassAtEntryPoint());
   187             this(getCallerClassAtEntryPoint(), ALL_MODES);
   148         }
       
   149 
       
   150         Lookup(Access token, Class<?> lookupClass) {
       
   151             // make sure we haven't accidentally picked up a privileged class:
   188             // make sure we haven't accidentally picked up a privileged class:
   152             checkUnprivilegedlookupClass(lookupClass);
   189             checkUnprivilegedlookupClass(lookupClass);
       
   190         }
       
   191 
       
   192         Lookup(Access token, Class<?> lookupClass) {
       
   193             this(lookupClass, ALL_MODES);
       
   194             Access.check(token);
       
   195         }
       
   196 
       
   197         private Lookup(Class<?> lookupClass, int allowedModes) {
   153             this.lookupClass = lookupClass;
   198             this.lookupClass = lookupClass;
       
   199             this.allowedModes = allowedModes;
   154         }
   200         }
   155 
   201 
   156         /**
   202         /**
   157          * Create a lookup on the specified class.
   203          * Create a lookup on the specified new lookup class.
   158          * The result is guaranteed to have no more access privileges
   204          * The resulting object will report the specified
   159          * than the original.
   205          * class as its own {@link #lookupClass}.
   160          */
   206          * <p>
   161         public Lookup in(Class<?> newLookupClass) {
   207          * However, the resulting {@code Lookup} object is guaranteed
   162             if (this == PUBLIC_LOOKUP)  return PUBLIC_LOOKUP;
   208          * to have no more access capabilities than the original.
   163             if (newLookupClass == null)  return PUBLIC_LOOKUP;
   209          * In particular:<ul>
   164             if (newLookupClass == lookupClass)  return this;
   210          * <li>If the new lookup class differs from the old one,
   165             if (this != IMPL_LOOKUP) {
   211          * protected members will not be accessible by virtue of inheritance.
   166                 if (!VerifyAccess.isSamePackage(lookupClass, newLookupClass))
   212          * <li>If the new lookup class is in a different package
   167                     throw newNoAccessException(new MemberName(newLookupClass), this);
   213          * than the old one, protected and default (package) members will not be accessible.
   168                 checkUnprivilegedlookupClass(newLookupClass);
   214          * <li>If the new lookup class is not within the same package member
       
   215          * as the old one, private members will not be accessible.
       
   216          * <li>In all cases, public members will continue to be accessible.
       
   217          * </ul>
       
   218          */
       
   219         public Lookup in(Class<?> requestedLookupClass) {
       
   220             requestedLookupClass.getClass();  // null check
       
   221             if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
       
   222                 return new Lookup(requestedLookupClass, ALL_MODES);
       
   223             if (requestedLookupClass == this.lookupClass)
       
   224                 return this;  // keep same capabilities
       
   225             int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
       
   226             if ((newModes & PACKAGE) != 0
       
   227                 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
       
   228                 newModes &= ~(PACKAGE|PRIVATE);
   169             }
   229             }
   170             return new Lookup(newLookupClass);
   230             if ((newModes & PRIVATE) != 0
   171         }
   231                 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
   172 
   232                 newModes &= ~PRIVATE;
   173         private Lookup(Class<?> lookupClass) {
   233             }
   174             this.lookupClass = lookupClass;
   234             checkUnprivilegedlookupClass(requestedLookupClass);
       
   235             return new Lookup(requestedLookupClass, newModes);
   175         }
   236         }
   176 
   237 
   177         // Make sure outer class is initialized first.
   238         // Make sure outer class is initialized first.
   178         static { IMPL_TOKEN.getClass(); }
   239         static { IMPL_TOKEN.getClass(); }
   179 
       
   180         private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
       
   181 
   240 
   182         /** Version of lookup which is trusted minimally.
   241         /** Version of lookup which is trusted minimally.
   183          *  It can only be used to create method handles to
   242          *  It can only be used to create method handles to
   184          *  publicly accessible members.
   243          *  publicly accessible members.
   185          */
   244          */
   186         static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
   245         static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
   187 
   246 
   188         /** Package-private version of lookup which is trusted. */
   247         /** Package-private version of lookup which is trusted. */
   189         static final Lookup IMPL_LOOKUP = new Lookup(null);
   248         static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
   190         static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
   249         static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
   191 
   250 
   192         private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
   251         private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
   193             String name = lookupClass.getName();
   252             String name = lookupClass.getName();
   194             if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
   253             if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
   195                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
   254                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
   196         }
   255         }
   197 
   256 
       
   257         /** Display the name of the class.
       
   258          *  If there are restrictions on the access permitted to this lookup,
       
   259          *  display those also.
       
   260          */
   198         @Override
   261         @Override
   199         public String toString() {
   262         public String toString() {
   200             if (lookupClass == PUBLIC_ONLY)
   263             String modestr;
   201                 return "public";
   264             String cname = lookupClass.getName();
   202             if (lookupClass == null)
   265             switch (allowedModes) {
   203                 return "privileged";
   266             case TRUSTED:
   204             return lookupClass.getName();
   267                 return "/trusted";
       
   268             case PUBLIC:
       
   269                 modestr = "/public";
       
   270                 if (lookupClass == Object.class)
       
   271                     return modestr;
       
   272                 break;
       
   273             case PUBLIC|PACKAGE:
       
   274                 return cname + "/package";
       
   275             case 0:  // should not happen
       
   276                 return cname + "/empty";
       
   277             case ALL_MODES:
       
   278                 return cname;
       
   279             }
       
   280             StringBuilder buf = new StringBuilder(cname);
       
   281             if ((allowedModes & PUBLIC) != 0)     buf.append("/public");
       
   282             if ((allowedModes & PACKAGE) != 0)    buf.append("/package");
       
   283             if ((allowedModes & PROTECTED) != 0)  buf.append("/protected");
       
   284             if ((allowedModes & PRIVATE) != 0)    buf.append("/private");
       
   285             return buf.toString();
   205         }
   286         }
   206 
   287 
   207         // call this from an entry point method in Lookup with extraFrames=0.
   288         // call this from an entry point method in Lookup with extraFrames=0.
   208         private static Class<?> getCallerClassAtEntryPoint() {
   289         private static Class<?> getCallerClassAtEntryPoint() {
   209             final int CALLER_DEPTH = 4;
   290             final int CALLER_DEPTH = 4;
   217         /**
   298         /**
   218          * Produce a method handle for a static method.
   299          * Produce a method handle for a static method.
   219          * The type of the method handle will be that of the method.
   300          * The type of the method handle will be that of the method.
   220          * (Since static methods do not take receivers, there is no
   301          * (Since static methods do not take receivers, there is no
   221          * additional receiver argument inserted into the method handle type,
   302          * additional receiver argument inserted into the method handle type,
   222          * as there would be with {@linkplain #findVirtual} or {@linkplain #findSpecial}.)
   303          * as there would be with {@link #findVirtual} or {@link #findSpecial}.)
   223          * The method and all its argument types must be accessible to the lookup class.
   304          * The method and all its argument types must be accessible to the lookup class.
   224          * If the method's class has not yet been initialized, that is done
   305          * If the method's class has not yet been initialized, that is done
   225          * immediately, before the method handle is returned.
   306          * immediately, before the method handle is returned.
   226          * @param defc the class from which the method is accessed
   307          * @param refc the class from which the method is accessed
   227          * @param name the name of the method
   308          * @param name the name of the method
   228          * @param type the type of the method
   309          * @param type the type of the method
   229          * @return the desired method handle
   310          * @return the desired method handle
   230          * @exception SecurityException <em>TBD</em>
   311          * @exception SecurityException <em>TBD</em>
   231          * @exception NoAccessException if the method does not exist or access checking fails
   312          * @exception NoAccessException if the method does not exist or access checking fails
   232          */
   313          */
   233         public
   314         public
   234         MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
   315         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException {
   235             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass());
   316             MemberName method = resolveOrFail(refc, name, type, true);
   236             VerifyAccess.checkName(method, this);
   317             checkMethod(refc, method, true);
   237             checkStatic(true, method, this);
   318             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
   238             //throw NoSuchMethodException
       
   239             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass());
       
   240         }
   319         }
   241 
   320 
   242         /**
   321         /**
   243          * Produce a method handle for a virtual method.
   322          * Produce a method handle for a virtual method.
   244          * The type of the method handle will be that of the method,
   323          * The type of the method handle will be that of the method,
   245          * with the receiver type ({@code defc}) prepended.
   324          * with the receiver type (usually {@code refc}) prepended.
   246          * The method and all its argument types must be accessible to the lookup class.
   325          * The method and all its argument types must be accessible to the lookup class.
   247          * <p>
   326          * <p>
   248          * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
   327          * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
   249          * of the receiver type, if the receiver type is not on the boot class path.
   328          * of the receiver type, if the receiver type is not on the boot class path.
   250          * This is due to a temporary JVM limitation, in which MethodHandle
   329          * This is due to a temporary JVM limitation, in which MethodHandle
   255          * When called, the handle will treat the first argument as a receiver
   334          * When called, the handle will treat the first argument as a receiver
   256          * and dispatch on the receiver's type to determine which method
   335          * and dispatch on the receiver's type to determine which method
   257          * implementation to enter.
   336          * implementation to enter.
   258          * (The dispatching action is identical with that performed by an
   337          * (The dispatching action is identical with that performed by an
   259          * {@code invokevirtual} or {@code invokeinterface} instruction.)
   338          * {@code invokevirtual} or {@code invokeinterface} instruction.)
   260          * @param defc the class or interface from which the method is accessed
   339          * @param refc the class or interface from which the method is accessed
   261          * @param name the name of the method
   340          * @param name the name of the method
   262          * @param type the type of the method, with the receiver argument omitted
   341          * @param type the type of the method, with the receiver argument omitted
   263          * @return the desired method handle
   342          * @return the desired method handle
   264          * @exception SecurityException <em>TBD</em>
   343          * @exception SecurityException <em>TBD</em>
   265          * @exception NoAccessException if the method does not exist or access checking fails
   344          * @exception NoAccessException if the method does not exist or access checking fails
   266          */
   345          */
   267         public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
   346         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException {
   268             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass());
   347             MemberName method = resolveOrFail(refc, name, type, false);
   269             VerifyAccess.checkName(method, this);
   348             checkMethod(refc, method, false);
   270             checkStatic(false, method, this);
   349             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   271             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
   350             return restrictProtectedReceiver(method, mh);
       
   351         }
       
   352 
       
   353         /**
       
   354          * Produce a method handle which creates an object and initializes it, using
       
   355          * the constructor of the specified type.
       
   356          * The parameter types of the method handle will be those of the constructor,
       
   357          * while the return type will be a reference to the constructor's class.
       
   358          * The constructor and all its argument types must be accessible to the lookup class.
       
   359          * If the constructor's class has not yet been initialized, that is done
       
   360          * immediately, before the method handle is returned.
       
   361          * <p>
       
   362          * Note:  The requested type must have a return type of {@code void}.
       
   363          * This is consistent with the JVM's treatment of constructor signatures.
       
   364          * @param refc the class or interface from which the method is accessed
       
   365          * @param type the type of the method, with the receiver argument omitted, and a void return type
       
   366          * @return the desired method handle
       
   367          * @exception SecurityException <em>TBD</em>
       
   368          * @exception NoAccessException if the method does not exist or access checking fails
       
   369          */
       
   370         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException {
       
   371             String name = "<init>";
       
   372             MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
       
   373             assert(ctor.isConstructor());
       
   374             checkAccess(refc, ctor);
       
   375             MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
       
   376             return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH);
   272         }
   377         }
   273 
   378 
   274         /**
   379         /**
   275          * Produce an early-bound method handle for a virtual method,
   380          * Produce an early-bound method handle for a virtual method,
   276          * as if called from an {@code invokespecial}
   381          * as if called from an {@code invokespecial}
   285          * (This direct invocation action is identical with that performed by an
   390          * (This direct invocation action is identical with that performed by an
   286          * {@code invokespecial} instruction.)
   391          * {@code invokespecial} instruction.)
   287          * <p>
   392          * <p>
   288          * If the explicitly specified caller class is not identical with the
   393          * If the explicitly specified caller class is not identical with the
   289          * lookup class, a security check TBD is performed.
   394          * lookup class, a security check TBD is performed.
   290          * @param defc the class or interface from which the method is accessed
   395          * @param refc the class or interface from which the method is accessed
   291          * @param name the name of the method, or "<init>" for a constructor
   396          * @param name the name of the method (which must not be "&lt;init&gt;")
   292          * @param type the type of the method, with the receiver argument omitted
   397          * @param type the type of the method, with the receiver argument omitted
   293          * @param specialCaller the proposed calling class to perform the {@code invokespecial}
   398          * @param specialCaller the proposed calling class to perform the {@code invokespecial}
   294          * @return the desired method handle
   399          * @return the desired method handle
   295          * @exception SecurityException <em>TBD</em>
   400          * @exception SecurityException <em>TBD</em>
   296          * @exception NoAccessException if the method does not exist or access checking fails
   401          * @exception NoAccessException if the method does not exist or access checking fails
   297          */
   402          */
   298         public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
   403         public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
   299                                         Class<?> specialCaller) throws NoAccessException {
   404                                         Class<?> specialCaller) throws NoAccessException {
   300             checkSpecialCaller(specialCaller, this);
   405             checkSpecialCaller(specialCaller);
   301             Lookup slookup = this.in(specialCaller);
   406             MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
   302             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, slookup.lookupClass());
   407             checkMethod(refc, method, false);
   303             VerifyAccess.checkName(method, this);
   408             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
   304             checkStatic(false, method, this);
   409             return restrictReceiver(method, mh, specialCaller);
   305             if (name.equals("<init>")) {
   410         }
   306                 throw newNoAccessException("cannot directly invoke a constructor", method, null);
   411 
   307             } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
   412         /**
   308                 throw newNoAccessException("method must be in a superclass of lookup class", method, slookup.lookupClass());
   413          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   309             }
   414          * Produce a method handle giving read access to a field.
   310             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, slookup.lookupClass());
   415          * The type of the method handle will have a return type of the field's
       
   416          * value type.
       
   417          * If the field is static, the method handle will take no arguments.
       
   418          * Otherwise, its single argument will be the instance containing
       
   419          * the field.
       
   420          * Access checking is performed immediately on behalf of the lookup class.
       
   421          * @param name the field's name
       
   422          * @param type the field's type
       
   423          * @param isStatic true if and only if the field is static
       
   424          * @return a method handle which can load values from the field
       
   425          * @exception NoAccessException if access checking fails
       
   426          */
       
   427         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
       
   428             return makeAccessor(refc, name, type, isStatic, false);
       
   429         }
       
   430 
       
   431         /**
       
   432          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   433          * Produce a method handle giving write access to a reflected field.
       
   434          * The type of the method handle will have a void return type.
       
   435          * If the field is static, the method handle will take a single
       
   436          * argument, of the field's value type, the value to be stored.
       
   437          * Otherwise, the two arguments will be the instance containing
       
   438          * the field, and the value to be stored.
       
   439          * Access checking is performed immediately on behalf of the lookup class.
       
   440          * @param name the field's name
       
   441          * @param type the field's type
       
   442          * @param isStatic true if and only if the field is static
       
   443          * @return a method handle which can store values into the reflected field
       
   444          * @exception NoAccessException if access checking fails
       
   445          */
       
   446         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type,
       
   447                                        boolean isStatic) throws NoAccessException {
       
   448             return makeAccessor(refc, name, type, isStatic, true);
   311         }
   449         }
   312 
   450 
   313         /**
   451         /**
   314          * Produce an early-bound method handle for a non-static method.
   452          * Produce an early-bound method handle for a non-static method.
   315          * The receiver must have a supertype {@code defc} in which a method
   453          * The receiver must have a supertype {@code defc} in which a method
   321          * so that every call to the method handle will invoke the
   459          * so that every call to the method handle will invoke the
   322          * requested method on the given receiver.
   460          * requested method on the given receiver.
   323          * <p>
   461          * <p>
   324          * This is equivalent to the following expression:
   462          * This is equivalent to the following expression:
   325          * <code>
   463          * <code>
   326          * {@link #insertArguments}({@link #findVirtual}(defc, name, type), receiver)
   464          * {@link #insertArguments insertArguments}({@link #findVirtual findVirtual}(defc, name, type), receiver)
   327          * </code>
   465          * </code>
   328          * where {@code defc} is either {@code receiver.getClass()} or a super
   466          * where {@code defc} is either {@code receiver.getClass()} or a super
   329          * type of that class, in which the requested method is accessible
   467          * type of that class, in which the requested method is accessible
   330          * to the lookup class.
   468          * to the lookup class.
   331          * @param receiver the object from which the method is accessed
   469          * @param receiver the object from which the method is accessed
   334          * @return the desired method handle
   472          * @return the desired method handle
   335          * @exception SecurityException <em>TBD</em>
   473          * @exception SecurityException <em>TBD</em>
   336          * @exception NoAccessException if the method does not exist or access checking fails
   474          * @exception NoAccessException if the method does not exist or access checking fails
   337          */
   475          */
   338         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
   476         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
   339             Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
   477             Class<? extends Object> refc = receiver.getClass(); // may get NPE
   340             MemberName reference = new MemberName(rcvc, name, type);
   478             MemberName method = resolveOrFail(refc, name, type, false);
   341             MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass());
   479             checkMethod(refc, method, false);
   342             VerifyAccess.checkName(method, this);
   480             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   343             checkStatic(false, method, this);
       
   344             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
       
   345             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   481             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   346             if (bmh == null)
   482             if (bmh == null)
   347                 throw newNoAccessException(method, this);
   483                 throw newNoAccessException(method, lookupClass());
   348             return bmh;
   484             return bmh;
   349         }
   485         }
   350 
   486 
   351         /**
   487         /**
   352          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   488          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   362          * @param m the reflected method
   498          * @param m the reflected method
   363          * @return a method handle which can invoke the reflected method
   499          * @return a method handle which can invoke the reflected method
   364          * @exception NoAccessException if access checking fails
   500          * @exception NoAccessException if access checking fails
   365          */
   501          */
   366         public MethodHandle unreflect(Method m) throws NoAccessException {
   502         public MethodHandle unreflect(Method m) throws NoAccessException {
   367             return unreflectImpl(new MemberName(m), m.isAccessible(), true, false, this);
   503             MemberName method = new MemberName(m);
       
   504             assert(method.isMethod());
       
   505             if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
       
   506             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
       
   507             if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
       
   508             return mh;
   368         }
   509         }
   369 
   510 
   370         /**
   511         /**
   371          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   512          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   372          * Produce a method handle for a reflected method.
   513          * Produce a method handle for a reflected method.
   373          * It will bypass checks for overriding methods on the receiver,
   514          * It will bypass checks for overriding methods on the receiver,
   374          * as if by the {@code invokespecial} instruction.
   515          * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
   375          * The type of the method handle will be that of the method,
   516          * The type of the method handle will be that of the method,
   376          * with the receiver type prepended.
   517          * with the special caller type prepended (and <em>not</em> the receiver of the method).
   377          * If the method's {@code accessible} flag is not set,
   518          * If the method's {@code accessible} flag is not set,
   378          * access checking is performed immediately on behalf of the lookup class,
   519          * access checking is performed immediately on behalf of the lookup class,
   379          * as if {@code invokespecial} instruction were being linked.
   520          * as if {@code invokespecial} instruction were being linked.
   380          * @param m the reflected method
   521          * @param m the reflected method
       
   522          * @param specialCaller the class nominally calling the method
   381          * @return a method handle which can invoke the reflected method
   523          * @return a method handle which can invoke the reflected method
   382          * @exception NoAccessException if access checking fails
   524          * @exception NoAccessException if access checking fails
   383          */
   525          */
   384         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
   526         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
   385             checkSpecialCaller(specialCaller, this);
   527             checkSpecialCaller(specialCaller);
   386             Lookup slookup = this.in(specialCaller);
   528             MemberName method = new MemberName(m);
   387             MemberName mname = new MemberName(m);
   529             assert(method.isMethod());
   388             checkStatic(false, mname, this);
   530             // ignore m.isAccessible:  this is a new kind of access
   389             return unreflectImpl(mname, m.isAccessible(), false, false, slookup);
   531             checkMethod(m.getDeclaringClass(), method, false);
       
   532             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
       
   533             return restrictReceiver(method, mh, specialCaller);
   390         }
   534         }
   391 
   535 
   392         /**
   536         /**
   393          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   537          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   394          * Produce a method handle for a reflected constructor.
   538          * Produce a method handle for a reflected constructor.
   398          * creating a new instance of the constructor's class on the
   542          * creating a new instance of the constructor's class on the
   399          * arguments passed to the method handle.
   543          * arguments passed to the method handle.
   400          * <p>
   544          * <p>
   401          * If the constructor's {@code accessible} flag is not set,
   545          * If the constructor's {@code accessible} flag is not set,
   402          * access checking is performed immediately on behalf of the lookup class.
   546          * access checking is performed immediately on behalf of the lookup class.
   403          * @param ctor the reflected constructor
   547          * @param c the reflected constructor
   404          * @return a method handle which can invoke the reflected constructor
   548          * @return a method handle which can invoke the reflected constructor
   405          * @exception NoAccessException if access checking fails
   549          * @exception NoAccessException if access checking fails
   406          */
   550          */
   407         public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
   551         public MethodHandle unreflectConstructor(Constructor c) throws NoAccessException {
   408             MemberName m = new MemberName(ctor);
   552             MemberName ctor = new MemberName(c);
   409             return unreflectImpl(m, ctor.isAccessible(), false, false, this);
   553             assert(ctor.isConstructor());
       
   554             if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
       
   555             MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
       
   556             return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
   410         }
   557         }
   411 
   558 
   412         /**
   559         /**
   413          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   560          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   414          * Produce a method handle giving read access to a reflected field.
   561          * Produce a method handle giving read access to a reflected field.
   422          * @param f the reflected field
   569          * @param f the reflected field
   423          * @return a method handle which can load values from the reflected field
   570          * @return a method handle which can load values from the reflected field
   424          * @exception NoAccessException if access checking fails
   571          * @exception NoAccessException if access checking fails
   425          */
   572          */
   426         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
   573         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
   427             MemberName m = new MemberName(f);
   574             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
   428             return unreflectImpl(m, f.isAccessible(), false, false, this);
       
   429         }
   575         }
   430 
   576 
   431         /**
   577         /**
   432          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   578          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   433          * Produce a method handle giving write access to a reflected field.
   579          * Produce a method handle giving write access to a reflected field.
   441          * @param f the reflected field
   587          * @param f the reflected field
   442          * @return a method handle which can store values into the reflected field
   588          * @return a method handle which can store values into the reflected field
   443          * @exception NoAccessException if access checking fails
   589          * @exception NoAccessException if access checking fails
   444          */
   590          */
   445         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
   591         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
   446             MemberName m = new MemberName(f);
   592             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
   447             return unreflectImpl(m, f.isAccessible(), false, true, this);
   593         }
   448         }
   594 
   449 
   595         /// Helper methods, all package-private.
   450     }
   596 
   451 
   597         MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
   452     static /*must not be public*/
   598             checkSymbolicClass(refc);  // do this before attempting to resolve
   453     MethodHandle findStaticFrom(Lookup lookup,
   599             int mods = (isStatic ? Modifier.STATIC : 0);
   454                                 Class<?> defc, String name, MethodType type) throws NoAccessException {
   600             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
   455         MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookup.lookupClass());
   601         }
   456         VerifyAccess.checkName(method, lookup);
   602 
   457         checkStatic(true, method, lookup);
   603         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
   458         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookup.lookupClass());
   604             checkSymbolicClass(refc);  // do this before attempting to resolve
   459     }
   605             int mods = (isStatic ? Modifier.STATIC : 0);
   460 
   606             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
   461     static void checkStatic(boolean wantStatic, MemberName m, Lookup lookup) {
   607         }
   462         if (wantStatic != m.isStatic()) {
   608 
   463             String message = wantStatic ? "expected a static method" : "expected a non-static method";
   609         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
   464             throw newNoAccessException(message, m, lookup.lookupClass());
   610                                  boolean searchSupers, Class<?> specialCaller) {
   465         }
   611             checkSymbolicClass(refc);  // do this before attempting to resolve
   466     }
   612             int mods = (isStatic ? Modifier.STATIC : 0);
   467 
   613             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
   468     static void checkSpecialCaller(Class<?> specialCaller, Lookup lookup) {
   614         }
   469         if (lookup == Lookup.IMPL_LOOKUP)
   615 
   470             return;  // privileged action
   616         void checkSymbolicClass(Class<?> refc) {
   471         assert(lookup.lookupClass() != null);
   617             Class<?> caller = lookupClassOrNull();
   472         if (!VerifyAccess.isSamePackageMember(specialCaller, lookup.lookupClass()))
   618             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
   473             throw newNoAccessException("no private access", new MemberName(specialCaller), lookup.lookupClass());
   619                 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
   474     }
   620         }
   475 
   621 
   476     // Helper for creating handles on reflected methods and constructors.
   622         void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
   477     static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
   623             String message;
   478                                       boolean doDispatch, boolean isSetter, Lookup lookup) {
   624             if (m.isConstructor())
   479         MethodType narrowMethodType = null;
   625                 message = "expected a method, not a constructor";
   480         Class<?> defc = m.getDeclaringClass();
   626             else if (!m.isMethod())
   481         boolean isSpecialInvoke = m.isInvocable() && !doDispatch;
   627                 message = "expected a method";
   482         int mods = m.getModifiers();
   628             else if (wantStatic != m.isStatic())
   483         if (m.isStatic()) {
   629                 message = wantStatic ? "expected a static method" : "expected a non-static method";
   484             if (!isAccessible &&
   630             else
   485                     VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), false) == null)
   631                 { checkAccess(refc, m); return; }
   486                 throw newNoAccessException(m, lookup);
   632             throw newNoAccessException(message, m, lookupClass());
   487         } else {
   633         }
   488             Class<?> constraint;
   634 
   489             if (isAccessible) {
   635         void checkAccess(Class<?> refc, MemberName m) {
   490                 // abbreviated access check for "unlocked" method
   636             int allowedModes = this.allowedModes;
   491                 constraint = doDispatch ? defc : lookup.lookupClass();
   637             if (allowedModes == TRUSTED)  return;
   492             } else {
   638             int mods = m.getModifiers();
   493                 constraint = VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), isSpecialInvoke);
   639             if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()))
       
   640                 return;  // common case
       
   641             int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
       
   642             if ((requestedModes & allowedModes) != 0
       
   643                 && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
       
   644                                                    mods, lookupClass()))
       
   645                 return;
       
   646             if (((requestedModes & ~allowedModes) & PROTECTED) != 0
       
   647                 && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
       
   648                 // Protected members can also be checked as if they were package-private.
       
   649                 return;
       
   650             throw newNoAccessException(accessFailedMessage(refc, m), m, lookupClass());
       
   651         }
       
   652 
       
   653         String accessFailedMessage(Class<?> refc, MemberName m) {
       
   654             Class<?> defc = m.getDeclaringClass();
       
   655             int mods = m.getModifiers();
       
   656             if (!VerifyAccess.isClassAccessible(defc, lookupClass()))
       
   657                 return "class is not public";
       
   658             if (refc != defc && !VerifyAccess.isClassAccessible(refc, lookupClass()))
       
   659                 return "symbolic reference "+refc.getName()+" is not public";
       
   660             if (Modifier.isPublic(mods))
       
   661                 return "access to public member failed";  // (how?)
       
   662             else if (allowedModes == PUBLIC)
       
   663                 return "member is not public";
       
   664             if (Modifier.isPrivate(mods))
       
   665                 return "member is private";
       
   666             if (Modifier.isProtected(mods))
       
   667                 return "member is protected";
       
   668             return "member is private to package";
       
   669         }
       
   670 
       
   671         void checkSpecialCaller(Class<?> specialCaller) {
       
   672             if (allowedModes == TRUSTED)  return;
       
   673             if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
       
   674                 throw newNoAccessException("no private access for invokespecial",
       
   675                                            new MemberName(specialCaller), lookupClass());
       
   676         }
       
   677 
       
   678         MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
       
   679             // The accessing class only has the right to use a protected member
       
   680             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
       
   681             if (!method.isProtected() || method.isStatic()
       
   682                 || allowedModes == TRUSTED
       
   683                 || VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))
       
   684                 return mh;
       
   685             else
       
   686                 return restrictReceiver(method, mh, lookupClass());
       
   687         }
       
   688         MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
       
   689             assert(!method.isStatic());
       
   690             Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
       
   691             if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
       
   692                 throw newNoAccessException("caller class must be a subclass below the method", method, caller);
   494             }
   693             }
   495             if (constraint == null) {
   694             MethodType rawType = mh.type();
   496                 throw newNoAccessException(m, lookup);
   695             if (rawType.parameterType(0) == caller)  return mh;
   497             }
   696             MethodType narrowType = rawType.changeParameterType(0, caller);
   498             if (constraint != defc && !constraint.isAssignableFrom(defc)) {
   697             return MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
   499                 if (!defc.isAssignableFrom(constraint))
   698         }
   500                     throw newNoAccessException("receiver must be in caller class", m, lookup.lookupClass());
   699 
   501                 if (m.isInvocable())
   700         MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
   502                     narrowMethodType = m.getInvocationType().changeParameterType(0, constraint);
   701                                   boolean isStatic, boolean isSetter) throws NoAccessException {
   503                 else if (m.isField())
   702             MemberName field = resolveOrFail(refc, name, type, isStatic);
   504                     narrowMethodType = (!isSetter
   703             if (isStatic != field.isStatic())
   505                                         ? MethodType.methodType(m.getFieldType(), constraint)
   704                 throw newNoAccessException(isStatic
   506                                         : MethodType.methodType(void.class, constraint, m.getFieldType()));
   705                                            ? "expected a static field"
   507             }
   706                                            : "expected a non-static field",
   508         }
   707                                            field, lookupClass());
   509         if (m.isInvocable())
   708             return makeAccessor(refc, field, false, isSetter);
   510             return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookup.lookupClass());
   709         }
   511         else if (m.isField())
   710 
   512             return MethodHandleImpl.accessField(IMPL_TOKEN, m, isSetter, lookup.lookupClass());
   711         MethodHandle makeAccessor(Class<?> refc, MemberName field,
   513         else
   712                                   boolean trusted, boolean isSetter) throws NoAccessException {
   514             throw new InternalError();
   713             assert(field.isField());
       
   714             if (trusted)
       
   715                 return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
       
   716             checkAccess(refc, field);
       
   717             MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
       
   718             return restrictProtectedReceiver(field, mh);
       
   719         }
   515     }
   720     }
   516 
   721 
   517     /**
   722     /**
   518      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   723      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   519      * Produce a method handle giving read access to elements of an array.
   724      * Produce a method handle giving read access to elements of an array.
   665      * </pre></blockquote>
   870      * </pre></blockquote>
   666      * @return a method handle which always invokes the call site's target
   871      * @return a method handle which always invokes the call site's target
   667      */
   872      */
   668     public static
   873     public static
   669     MethodHandle dynamicInvoker(CallSite site) {
   874     MethodHandle dynamicInvoker(CallSite site) {
   670         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, CallSite.GET_TARGET, site);
   875         MethodHandle getCSTarget = GET_TARGET;
       
   876         if (getCSTarget == null)
       
   877             GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
       
   878                 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
       
   879         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
   671         MethodHandle invoker = exactInvoker(site.type());
   880         MethodHandle invoker = exactInvoker(site.type());
   672         return foldArguments(invoker, getTarget);
   881         return foldArguments(invoker, getTarget);
   673     }
   882     }
       
   883     private static MethodHandle GET_TARGET = null;  // link this lazily, not eagerly
   674 
   884 
   675     static Invokers invokers(MethodType type) {
   885     static Invokers invokers(MethodType type) {
   676         return MethodTypeImpl.invokers(IMPL_TOKEN, type);
   886         return MethodTypeImpl.invokers(IMPL_TOKEN, type);
   677     }
   887     }
   678 
   888 
  1023      * <p>
  1233      * <p>
  1024      * <b>Example:</b>
  1234      * <b>Example:</b>
  1025      * <p><blockquote><pre>
  1235      * <p><blockquote><pre>
  1026      *   MethodHandle cat = MethodHandles.lookup().
  1236      *   MethodHandle cat = MethodHandles.lookup().
  1027      *     findVirtual(String.class, "concat", String.class, String.class);
  1237      *     findVirtual(String.class, "concat", String.class, String.class);
  1028      *   System.out.println(cat.&lt;String&gt;invoke("x", "y")); // xy
  1238      *   System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy
  1029      *   MethodHandle d0 = dropArguments(cat, 0, String.class);
  1239      *   MethodHandle d0 = dropArguments(cat, 0, String.class);
  1030      *   System.out.println(d0.&lt;String&gt;invoke("x", "y", "z")); // xy
  1240      *   System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy
  1031      *   MethodHandle d1 = dropArguments(cat, 1, String.class);
  1241      *   MethodHandle d1 = dropArguments(cat, 1, String.class);
  1032      *   System.out.println(d1.&lt;String&gt;invoke("x", "y", "z")); // xz
  1242      *   System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz
  1033      *   MethodHandle d2 = dropArguments(cat, 2, String.class);
  1243      *   MethodHandle d2 = dropArguments(cat, 2, String.class);
  1034      *   System.out.println(d2.&lt;String&gt;invoke("x", "y", "z")); // yz
  1244      *   System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz
  1035      *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
  1245      *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
  1036      *   System.out.println(d12.&lt;String&gt;invoke("w", "x", "y", "z")); // wz
  1246      *   System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz
  1037      * </pre></blockquote>
  1247      * </pre></blockquote>
  1038      * @param target the method handle to invoke after the argument is dropped
  1248      * @param target the method handle to invoke after the argument is dropped
  1039      * @param valueTypes the type(s) of the argument to drop
  1249      * @param valueTypes the type(s) of the argument to drop
  1040      * @param pos which argument to drop (zero for the first)
  1250      * @param pos which argument to drop (zero for the first)
  1041      * @return a new method handle which drops an argument of the given type,
  1251      * @return a new method handle which drops an argument of the given type,
  1252             choose = appendArgument(choose, target);
  1462             choose = appendArgument(choose, target);
  1253             choose = appendArgument(choose, fallback);
  1463             choose = appendArgument(choose, fallback);
  1254             MethodHandle dispatch = compose(choose, test);
  1464             MethodHandle dispatch = compose(choose, test);
  1255             // dispatch = \(a...).(test(a...) ? target : fallback)
  1465             // dispatch = \(a...).(test(a...) ? target : fallback)
  1256             return combineArguments(invoke, dispatch, 0);
  1466             return combineArguments(invoke, dispatch, 0);
  1257             // return \(a...).((test(a...) ? target : fallback).invoke(a...))
  1467             // return \(a...).((test(a...) ? target : fallback).invokeExact(a...))
  1258         } */
  1468         } */
  1259         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
  1469         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
  1260     }
  1470     }
  1261 
  1471 
  1262     static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
  1472     static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
  1323      */
  1533      */
  1324     public static
  1534     public static
  1325     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
  1535     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
  1326         return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
  1536         return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
  1327     }
  1537     }
  1328 
       
  1329     /** Alias for {@link MethodType#methodType}. */
       
  1330     @Deprecated // "use MethodType.methodType instead"
       
  1331     public static MethodType methodType(Class<?> rtype) {
       
  1332         return MethodType.methodType(rtype);
       
  1333     }
       
  1334 
       
  1335     /** Alias for {@link MethodType#methodType}. */
       
  1336     @Deprecated // "use MethodType.methodType instead"
       
  1337     public static MethodType methodType(Class<?> rtype, Class<?> ptype) {
       
  1338         return MethodType.methodType(rtype, ptype);
       
  1339     }
       
  1340 
       
  1341     /** Alias for {@link MethodType#methodType}. */
       
  1342     @Deprecated // "use MethodType.methodType instead"
       
  1343     public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
       
  1344         return MethodType.methodType(rtype, ptype0, ptypes);
       
  1345     }
       
  1346 }
  1538 }