< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 



  28 import jdk.internal.reflect.CallerSensitive;
  29 import jdk.internal.reflect.Reflection;
  30 import jdk.internal.vm.annotation.ForceInline;
  31 import sun.invoke.util.ValueConversions;
  32 import sun.invoke.util.VerifyAccess;
  33 import sun.invoke.util.Wrapper;
  34 import sun.reflect.misc.ReflectUtil;
  35 import sun.security.util.SecurityConstants;
  36 
  37 import java.lang.invoke.LambdaForm.BasicType;
  38 import java.lang.reflect.Constructor;
  39 import java.lang.reflect.Field;
  40 import java.lang.reflect.Member;
  41 import java.lang.reflect.Method;
  42 import java.lang.reflect.Modifier;
  43 import java.lang.reflect.Module;
  44 import java.lang.reflect.ReflectPermission;
  45 import java.nio.ByteOrder;



  46 import java.util.ArrayList;
  47 import java.util.Arrays;
  48 import java.util.BitSet;
  49 import java.util.Iterator;
  50 import java.util.List;
  51 import java.util.Objects;
  52 import java.util.concurrent.ConcurrentHashMap;
  53 import java.util.stream.Collectors;
  54 import java.util.stream.Stream;
  55 
  56 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
  57 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  58 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
  59 import static java.lang.invoke.MethodType.methodType;
  60 
  61 /**
  62  * This class consists exclusively of static methods that operate on or return
  63  * method handles. They fall into several categories:
  64  * <ul>
  65  * <li>Lookup methods which help create method handles for methods and fields.


 174      */
 175     public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException {
 176         SecurityManager sm = System.getSecurityManager();
 177         if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
 178         if (targetClass.isPrimitive())
 179             throw new IllegalArgumentException(targetClass + " is a primitive class");
 180         if (targetClass.isArray())
 181             throw new IllegalArgumentException(targetClass + " is an array class");
 182         Module targetModule = targetClass.getModule();
 183         Module callerModule = lookup.lookupClass().getModule();
 184         if (!callerModule.canRead(targetModule))
 185             throw new IllegalAccessException(callerModule + " does not read " + targetModule);
 186         if (targetModule.isNamed()) {
 187             String pn = targetClass.getPackageName();
 188             assert pn.length() > 0 : "unnamed package cannot be in named module";
 189             if (!targetModule.isOpen(pn, callerModule))
 190                 throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule);
 191         }
 192         if ((lookup.lookupModes() & Lookup.MODULE) == 0)
 193             throw new IllegalAccessException("lookup does not have MODULE lookup mode");






 194         return new Lookup(targetClass);
 195     }
 196 
 197     /**
 198      * Performs an unchecked "crack" of a
 199      * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
 200      * The result is as if the user had obtained a lookup object capable enough
 201      * to crack the target method handle, called
 202      * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
 203      * on the target to obtain its symbolic reference, and then called
 204      * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
 205      * to resolve the symbolic reference to a member.
 206      * <p>
 207      * If there is a security manager, its {@code checkPermission} method
 208      * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
 209      * @param <T> the desired type of the result, either {@link Member} or a subtype
 210      * @param target a direct method handle to crack into symbolic reference components
 211      * @param expected a class object representing the desired result type {@code T}
 212      * @return a reference to the method, constructor, or field object
 213      * @exception SecurityException if the caller is not privileged to call {@code setAccessible}


 838          * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE} or {@code UNCONDITIONAL}
 839          * @see MethodHandles#privateLookupIn
 840          * @since 9
 841          */
 842         public Lookup dropLookupMode(int modeToDrop) {
 843             int oldModes = lookupModes();
 844             int newModes = oldModes & ~(modeToDrop | PROTECTED | UNCONDITIONAL);
 845             switch (modeToDrop) {
 846                 case PUBLIC: newModes &= ~(ALL_MODES); break;
 847                 case MODULE: newModes &= ~(PACKAGE | PRIVATE); break;
 848                 case PACKAGE: newModes &= ~(PRIVATE); break;
 849                 case PROTECTED:
 850                 case PRIVATE:
 851                 case UNCONDITIONAL: break;
 852                 default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop");
 853             }
 854             if (newModes == oldModes) return this;  // return self if no change
 855             return new Lookup(lookupClass(), newModes);
 856         }
 857 










































































































 858         // Make sure outer class is initialized first.
 859         static { IMPL_NAMES.getClass(); }
 860 
 861         /** Package-private version of lookup which is trusted. */
 862         static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
 863 
 864         /** Version of lookup which is trusted minimally.
 865          *  It can only be used to create method handles to publicly accessible
 866          *  members in packages that are exported unconditionally.
 867          */
 868         static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, (PUBLIC|UNCONDITIONAL));
 869 
 870         private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
 871             String name = lookupClass.getName();
 872             if (name.startsWith("java.lang.invoke."))
 873                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
 874 
 875             // For caller-sensitive MethodHandles.lookup() disallow lookup from
 876             // restricted packages.  This a fragile and blunt approach.
 877             // TODO replace with a more formal and less fragile mechanism


1931         /**
1932          * Find my trustable caller class if m is a caller sensitive method.
1933          * If this lookup object has private access, then the caller class is the lookupClass.
1934          * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
1935          */
1936         Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
1937             Class<?> callerClass = null;
1938             if (MethodHandleNatives.isCallerSensitive(m)) {
1939                 // Only lookups with private access are allowed to resolve caller-sensitive methods
1940                 if (hasPrivateAccess()) {
1941                     callerClass = lookupClass;
1942                 } else {
1943                     throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
1944                 }
1945             }
1946             return callerClass;
1947         }
1948 
1949         /**
1950          * Returns {@code true} if this lookup has {@code PRIVATE} access.
1951          * @return {@code true} if this lookup has {@code PRIVATE} acesss.
1952          * @since 9
1953          */
1954         public boolean hasPrivateAccess() {
1955             return (allowedModes & PRIVATE) != 0;
1956         }
1957 
1958         /**
1959          * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
1960          * Determines a trustable caller class to compare with refc, the symbolic reference class.
1961          * If this lookup object has private access, then the caller class is the lookupClass.
1962          */
1963         void checkSecurityManager(Class<?> refc, MemberName m) {
1964             SecurityManager smgr = System.getSecurityManager();
1965             if (smgr == null)  return;
1966             if (allowedModes == TRUSTED)  return;
1967 
1968             // Step 1:
1969             boolean fullPowerLookup = hasPrivateAccess();
1970             if (!fullPowerLookup ||
1971                 !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.misc.SharedSecrets;
  29 import jdk.internal.module.IllegalAccessLogger;
  30 import jdk.internal.org.objectweb.asm.ClassReader;
  31 import jdk.internal.reflect.CallerSensitive;
  32 import jdk.internal.reflect.Reflection;
  33 import jdk.internal.vm.annotation.ForceInline;
  34 import sun.invoke.util.ValueConversions;
  35 import sun.invoke.util.VerifyAccess;
  36 import sun.invoke.util.Wrapper;
  37 import sun.reflect.misc.ReflectUtil;
  38 import sun.security.util.SecurityConstants;
  39 
  40 import java.lang.invoke.LambdaForm.BasicType;
  41 import java.lang.reflect.Constructor;
  42 import java.lang.reflect.Field;
  43 import java.lang.reflect.Member;
  44 import java.lang.reflect.Method;
  45 import java.lang.reflect.Modifier;
  46 import java.lang.reflect.Module;
  47 import java.lang.reflect.ReflectPermission;
  48 import java.nio.ByteOrder;
  49 import java.security.AccessController;
  50 import java.security.PrivilegedAction;
  51 import java.security.ProtectionDomain;
  52 import java.util.ArrayList;
  53 import java.util.Arrays;
  54 import java.util.BitSet;
  55 import java.util.Iterator;
  56 import java.util.List;
  57 import java.util.Objects;
  58 import java.util.concurrent.ConcurrentHashMap;
  59 import java.util.stream.Collectors;
  60 import java.util.stream.Stream;
  61 
  62 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
  63 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  64 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
  65 import static java.lang.invoke.MethodType.methodType;
  66 
  67 /**
  68  * This class consists exclusively of static methods that operate on or return
  69  * method handles. They fall into several categories:
  70  * <ul>
  71  * <li>Lookup methods which help create method handles for methods and fields.


 180      */
 181     public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException {
 182         SecurityManager sm = System.getSecurityManager();
 183         if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
 184         if (targetClass.isPrimitive())
 185             throw new IllegalArgumentException(targetClass + " is a primitive class");
 186         if (targetClass.isArray())
 187             throw new IllegalArgumentException(targetClass + " is an array class");
 188         Module targetModule = targetClass.getModule();
 189         Module callerModule = lookup.lookupClass().getModule();
 190         if (!callerModule.canRead(targetModule))
 191             throw new IllegalAccessException(callerModule + " does not read " + targetModule);
 192         if (targetModule.isNamed()) {
 193             String pn = targetClass.getPackageName();
 194             assert pn.length() > 0 : "unnamed package cannot be in named module";
 195             if (!targetModule.isOpen(pn, callerModule))
 196                 throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule);
 197         }
 198         if ((lookup.lookupModes() & Lookup.MODULE) == 0)
 199             throw new IllegalAccessException("lookup does not have MODULE lookup mode");
 200         if (!callerModule.isNamed() && targetModule.isNamed()) {
 201             IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
 202             if (logger != null) {
 203                 logger.logIfOpenedByBackdoor(lookup, targetClass);
 204             }
 205         }
 206         return new Lookup(targetClass);
 207     }
 208 
 209     /**
 210      * Performs an unchecked "crack" of a
 211      * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
 212      * The result is as if the user had obtained a lookup object capable enough
 213      * to crack the target method handle, called
 214      * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
 215      * on the target to obtain its symbolic reference, and then called
 216      * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
 217      * to resolve the symbolic reference to a member.
 218      * <p>
 219      * If there is a security manager, its {@code checkPermission} method
 220      * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
 221      * @param <T> the desired type of the result, either {@link Member} or a subtype
 222      * @param target a direct method handle to crack into symbolic reference components
 223      * @param expected a class object representing the desired result type {@code T}
 224      * @return a reference to the method, constructor, or field object
 225      * @exception SecurityException if the caller is not privileged to call {@code setAccessible}


 850          * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE} or {@code UNCONDITIONAL}
 851          * @see MethodHandles#privateLookupIn
 852          * @since 9
 853          */
 854         public Lookup dropLookupMode(int modeToDrop) {
 855             int oldModes = lookupModes();
 856             int newModes = oldModes & ~(modeToDrop | PROTECTED | UNCONDITIONAL);
 857             switch (modeToDrop) {
 858                 case PUBLIC: newModes &= ~(ALL_MODES); break;
 859                 case MODULE: newModes &= ~(PACKAGE | PRIVATE); break;
 860                 case PACKAGE: newModes &= ~(PRIVATE); break;
 861                 case PROTECTED:
 862                 case PRIVATE:
 863                 case UNCONDITIONAL: break;
 864                 default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop");
 865             }
 866             if (newModes == oldModes) return this;  // return self if no change
 867             return new Lookup(lookupClass(), newModes);
 868         }
 869 
 870         /**
 871          * Defines a class to the same class loader and in the same runtime package and
 872          * {@linkplain java.security.ProtectionDomain protection domain} as this lookup's
 873          * {@linkplain #lookupClass() lookup class}.
 874          *
 875          * <p> The {@linkplain #lookupModes() lookup modes} for this lookup must include
 876          * {@link #PACKAGE PACKAGE} access as default (package) members will be
 877          * accessible to the class. The {@code PACKAGE} lookup mode serves to authenticate
 878          * that the lookup object was created by a caller in the runtime package (or derived
 879          * from a lookup originally created by suitably privileged code to a target class in
 880          * the runtime package). The lookup modes cannot include {@link #PRIVATE PRIVATE}
 881          * access. A lookup with {@code PRIVATE} access can be downgraded to drop this lookup
 882          * mode with the {@linkplain #dropLookupMode(int) dropLookupMode} method. </p>
 883          *
 884          * <p> The {@code bytes} parameter is the class bytes of a valid class file (as defined
 885          * by the <em>The Java Virtual Machine Specification</em>) with a class name in the
 886          * same package as the lookup class. </p>
 887          *
 888          * <p> This method does not run the class initializer. The class initializer may
 889          * run at a later time, as detailed in section 12.4 of the <em>The Java Language
 890          * Specification</em>. </p>
 891          *
 892          * <p> If there is a security manager, its {@code checkPermission} method is first called
 893          * to check {@code RuntimePermission("defineClass")}. </p>
 894          *
 895          * @param bytes the class bytes
 896          * @return the {@code Class} object for the class
 897          * @throws IllegalArgumentException the bytes are for a class in a different package
 898          * to the lookup class
 899          * @throws IllegalAccessException if this lookup does not have {@code PACKAGE} access
 900          * @throws UnsupportedOperationException if the lookup class has {@code PRIVATE} access
 901          * @throws LinkageError if the class is malformed ({@code ClassFormatError}), cannot be
 902          * verified ({@code VerifyError}), is already defined, or another linkage error occurs
 903          * @throws SecurityException if denied by the security manager
 904          * @throws NullPointerException if {@code bytes} is {@code null}
 905          * @since 9
 906          * @spec JPMS
 907          * @see Lookup#privateLookupIn
 908          * @see Lookup#dropLookupMode
 909          * @see ClassLoader#defineClass(String,byte[],int,int,ProtectionDomain)
 910          */
 911         public Class<?> defineClass(byte[] bytes) throws IllegalAccessException {
 912             SecurityManager sm = System.getSecurityManager();
 913             if (sm != null)
 914                 sm.checkPermission(new RuntimePermission("defineClass"));
 915             if (hasPrivateAccess())
 916                 throw new UnsupportedOperationException("PRIVATE access not supported");
 917             if ((lookupModes() & PACKAGE) == 0)
 918                 throw new IllegalAccessException("Lookup does not have PACKAGE access");
 919             assert (lookupModes() & (MODULE|PUBLIC)) != 0;
 920 
 921             // parse class bytes to get class name (in internal form)
 922             bytes = bytes.clone();
 923             String name;
 924             try {
 925                 ClassReader reader = new ClassReader(bytes);
 926                 name = reader.getClassName();
 927             } catch (RuntimeException e) {
 928                 // ASM exceptions are poorly specified
 929                 ClassFormatError cfe = new ClassFormatError();
 930                 cfe.initCause(e);
 931                 throw cfe;
 932             }
 933 
 934             // get package and class name in binary form
 935             String cn, pn;
 936             int index = name.lastIndexOf('/');
 937             if (index == -1) {
 938                 cn = name;
 939                 pn = "";
 940             } else {
 941                 cn = name.replace('/', '.');
 942                 pn = cn.substring(0, index);
 943             }
 944             if (!pn.equals(lookupClass.getPackageName())) {
 945                 throw new IllegalArgumentException("Class not in same package as lookup class");
 946             }
 947 
 948             // invoke the class loader's defineClass method
 949             ClassLoader loader = lookupClass.getClassLoader();
 950             ProtectionDomain pd = (loader != null) ? lookupClassProtectionDomain() : null;
 951             String source = "__Lookup_defineClass__";
 952             Class<?> clazz = SharedSecrets.getJavaLangAccess().defineClass(loader, cn, bytes, pd, source);
 953             assert clazz.getClassLoader() == lookupClass.getClassLoader()
 954                     && clazz.getPackageName().equals(lookupClass.getPackageName())
 955                     && protectionDomain(clazz) == lookupClassProtectionDomain();
 956             return clazz;
 957         }
 958 
 959         private ProtectionDomain lookupClassProtectionDomain() {
 960             ProtectionDomain pd = cachedProtectionDomain;
 961             if (pd == null) {
 962                 cachedProtectionDomain = pd = protectionDomain(lookupClass);
 963             }
 964             return pd;
 965         }
 966 
 967         private ProtectionDomain protectionDomain(Class<?> clazz) {
 968             PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
 969             return AccessController.doPrivileged(pa);
 970         }
 971 
 972         // cached protection domain
 973         private volatile ProtectionDomain cachedProtectionDomain;
 974 
 975 
 976         // Make sure outer class is initialized first.
 977         static { IMPL_NAMES.getClass(); }
 978 
 979         /** Package-private version of lookup which is trusted. */
 980         static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
 981 
 982         /** Version of lookup which is trusted minimally.
 983          *  It can only be used to create method handles to publicly accessible
 984          *  members in packages that are exported unconditionally.
 985          */
 986         static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, (PUBLIC|UNCONDITIONAL));
 987 
 988         private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
 989             String name = lookupClass.getName();
 990             if (name.startsWith("java.lang.invoke."))
 991                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
 992 
 993             // For caller-sensitive MethodHandles.lookup() disallow lookup from
 994             // restricted packages.  This a fragile and blunt approach.
 995             // TODO replace with a more formal and less fragile mechanism


2049         /**
2050          * Find my trustable caller class if m is a caller sensitive method.
2051          * If this lookup object has private access, then the caller class is the lookupClass.
2052          * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
2053          */
2054         Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
2055             Class<?> callerClass = null;
2056             if (MethodHandleNatives.isCallerSensitive(m)) {
2057                 // Only lookups with private access are allowed to resolve caller-sensitive methods
2058                 if (hasPrivateAccess()) {
2059                     callerClass = lookupClass;
2060                 } else {
2061                     throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
2062                 }
2063             }
2064             return callerClass;
2065         }
2066 
2067         /**
2068          * Returns {@code true} if this lookup has {@code PRIVATE} access.
2069          * @return {@code true} if this lookup has {@code PRIVATE} access.
2070          * @since 9
2071          */
2072         public boolean hasPrivateAccess() {
2073             return (allowedModes & PRIVATE) != 0;
2074         }
2075 
2076         /**
2077          * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
2078          * Determines a trustable caller class to compare with refc, the symbolic reference class.
2079          * If this lookup object has private access, then the caller class is the lookupClass.
2080          */
2081         void checkSecurityManager(Class<?> refc, MemberName m) {
2082             SecurityManager smgr = System.getSecurityManager();
2083             if (smgr == null)  return;
2084             if (allowedModes == TRUSTED)  return;
2085 
2086             // Step 1:
2087             boolean fullPowerLookup = hasPrivateAccess();
2088             if (!fullPowerLookup ||
2089                 !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {


< prev index next >