jdk/src/share/classes/java/dyn/MethodHandles.java
changeset 8347 e5daa5772ffd
parent 8346 3b891698c4ec
child 8349 e1ba54c43609
equal deleted inserted replaced
8346:3b891698c4ec 8347:e5daa5772ffd
   224      * <p>
   224      * <p>
   225      * A lookup can fail, because
   225      * A lookup can fail, because
   226      * the containing class is not accessible to the lookup class, or
   226      * the containing class is not accessible to the lookup class, or
   227      * because the desired class member is missing, or because the
   227      * because the desired class member is missing, or because the
   228      * desired class member is not accessible to the lookup class.
   228      * desired class member is not accessible to the lookup class.
   229      * It can also fail if a security manager is installed and refuses
   229      * In any of these cases, a {@code ReflectiveOperationException} will be
   230      * access.  In any of these cases, an exception will be
   230      * thrown from the attempted lookup.  The exact class will be one of
   231      * thrown from the attempted lookup.
   231      * the following:
       
   232      * <ul>
       
   233      * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
       
   234      * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
       
   235      * <li>IllegalAccessException &mdash; if the member exists but an access check fails
       
   236      * </ul>
   232      * <p>
   237      * <p>
   233      * In general, the conditions under which a method handle may be
   238      * In general, the conditions under which a method handle may be
   234      * looked up for a method {@code M} are exactly equivalent to the conditions
   239      * looked up for a method {@code M} are exactly equivalent to the conditions
   235      * under which the lookup class could have compiled and resolved a call to {@code M}.
   240      * under which the lookup class could have compiled and resolved a call to {@code M}.
   236      * And the effect of invoking the method handle resulting from the lookup
   241      * And the effect of invoking the method handle resulting from the lookup
   509          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   514          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   510          * @param refc the class from which the method is accessed
   515          * @param refc the class from which the method is accessed
   511          * @param name the name of the method
   516          * @param name the name of the method
   512          * @param type the type of the method
   517          * @param type the type of the method
   513          * @return the desired method handle
   518          * @return the desired method handle
   514          * @exception NoAccessException if the method does not exist or access checking fails
   519          * @throws NoSuchMethodException if the method does not exist
       
   520          * @throws IllegalAccessException if access checking fails, or if the method is not {@code static}
       
   521          * @throws NullPointerException if any argument is null
   515          */
   522          */
   516         public
   523         public
   517         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException {
   524         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
   518             MemberName method = resolveOrFail(refc, name, type, true);
   525             MemberName method = resolveOrFail(refc, name, type, true);
   519             checkMethod(refc, method, true);
   526             checkMethod(refc, method, true);
   520             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
   527             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
   521         }
   528         }
   522 
   529 
   547          *
   554          *
   548          * @param refc the class or interface from which the method is accessed
   555          * @param refc the class or interface from which the method is accessed
   549          * @param name the name of the method
   556          * @param name the name of the method
   550          * @param type the type of the method, with the receiver argument omitted
   557          * @param type the type of the method, with the receiver argument omitted
   551          * @return the desired method handle
   558          * @return the desired method handle
   552          * @exception NoAccessException if the method does not exist or access checking fails
   559          * @throws NoSuchMethodException if the method does not exist
   553          */
   560          * @throws IllegalAccessException if access checking fails, or if the method is {@code static}
   554         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException {
   561          * @throws NullPointerException if any argument is null
       
   562          */
       
   563         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
   555             MemberName method = resolveOrFail(refc, name, type, false);
   564             MemberName method = resolveOrFail(refc, name, type, false);
   556             checkMethod(refc, method, false);
   565             checkMethod(refc, method, false);
   557             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   566             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   558             return restrictProtectedReceiver(method, mh);
   567             return restrictProtectedReceiver(method, mh);
   559         }
   568         }
   574          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   583          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   575          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
   584          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
   576          * @param refc the class or interface from which the method is accessed
   585          * @param refc the class or interface from which the method is accessed
   577          * @param type the type of the method, with the receiver argument omitted, and a void return type
   586          * @param type the type of the method, with the receiver argument omitted, and a void return type
   578          * @return the desired method handle
   587          * @return the desired method handle
   579          * @exception NoAccessException if the method does not exist or access checking fails
   588          * @throws NoSuchMethodException if the constructor does not exist
   580          */
   589          * @throws IllegalAccessException if access checking fails
   581         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException {
   590          * @throws NullPointerException if any argument is null
       
   591          */
       
   592         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
   582             String name = "<init>";
   593             String name = "<init>";
   583             MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
   594             MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
   584             assert(ctor.isConstructor());
   595             assert(ctor.isConstructor());
   585             checkAccess(refc, ctor);
   596             checkAccess(refc, ctor);
   586             MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
   597             MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
   627          * @param refc the class or interface from which the method is accessed
   638          * @param refc the class or interface from which the method is accessed
   628          * @param name the name of the method (which must not be "&lt;init&gt;")
   639          * @param name the name of the method (which must not be "&lt;init&gt;")
   629          * @param type the type of the method, with the receiver argument omitted
   640          * @param type the type of the method, with the receiver argument omitted
   630          * @param specialCaller the proposed calling class to perform the {@code invokespecial}
   641          * @param specialCaller the proposed calling class to perform the {@code invokespecial}
   631          * @return the desired method handle
   642          * @return the desired method handle
   632          * @exception NoAccessException if the method does not exist or access checking fails
   643          * @throws NoSuchMethodException if the method does not exist
       
   644          * @throws IllegalAccessException if access checking fails
       
   645          * @throws NullPointerException if any argument is null
   633          */
   646          */
   634         public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
   647         public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
   635                                         Class<?> specialCaller) throws NoAccessException {
   648                                         Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
   636             checkSpecialCaller(specialCaller);
   649             checkSpecialCaller(specialCaller);
   637             MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
   650             MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
   638             checkMethod(refc, method, false);
   651             checkMethod(refc, method, false);
   639             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
   652             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
   640             return restrictReceiver(method, mh, specialCaller);
   653             return restrictReceiver(method, mh, specialCaller);
   649          * Access checking is performed immediately on behalf of the lookup class.
   662          * Access checking is performed immediately on behalf of the lookup class.
   650          * @param refc the class or interface from which the method is accessed
   663          * @param refc the class or interface from which the method is accessed
   651          * @param name the field's name
   664          * @param name the field's name
   652          * @param type the field's type
   665          * @param type the field's type
   653          * @return a method handle which can load values from the field
   666          * @return a method handle which can load values from the field
   654          * @exception NoAccessException if access checking fails
   667          * @throws NoSuchFieldException if the field does not exist
   655          */
   668          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
   656         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
   669          * @throws NullPointerException if any argument is null
       
   670          */
       
   671         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
   657             return makeAccessor(refc, name, type, false, false);
   672             return makeAccessor(refc, name, type, false, false);
   658         }
   673         }
   659 
   674 
   660         /**
   675         /**
   661          * Produces a method handle giving write access to a non-static field.
   676          * Produces a method handle giving write access to a non-static field.
   666          * Access checking is performed immediately on behalf of the lookup class.
   681          * Access checking is performed immediately on behalf of the lookup class.
   667          * @param refc the class or interface from which the method is accessed
   682          * @param refc the class or interface from which the method is accessed
   668          * @param name the field's name
   683          * @param name the field's name
   669          * @param type the field's type
   684          * @param type the field's type
   670          * @return a method handle which can store values into the field
   685          * @return a method handle which can store values into the field
   671          * @exception NoAccessException if access checking fails
   686          * @throws NoSuchFieldException if the field does not exist
   672          */
   687          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
   673         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
   688          * @throws NullPointerException if any argument is null
       
   689          */
       
   690         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
   674             return makeAccessor(refc, name, type, false, true);
   691             return makeAccessor(refc, name, type, false, true);
   675         }
   692         }
   676 
   693 
   677         /**
   694         /**
   678          * Produces a method handle giving read access to a static field.
   695          * Produces a method handle giving read access to a static field.
   682          * Access checking is performed immediately on behalf of the lookup class.
   699          * Access checking is performed immediately on behalf of the lookup class.
   683          * @param refc the class or interface from which the method is accessed
   700          * @param refc the class or interface from which the method is accessed
   684          * @param name the field's name
   701          * @param name the field's name
   685          * @param type the field's type
   702          * @param type the field's type
   686          * @return a method handle which can load values from the field
   703          * @return a method handle which can load values from the field
   687          * @exception NoAccessException if access checking fails
   704          * @throws NoSuchFieldException if the field does not exist
   688          */
   705          * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
   689         public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
   706          * @throws NullPointerException if any argument is null
       
   707          */
       
   708         public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
   690             return makeAccessor(refc, name, type, true, false);
   709             return makeAccessor(refc, name, type, true, false);
   691         }
   710         }
   692 
   711 
   693         /**
   712         /**
   694          * Produces a method handle giving write access to a static field.
   713          * Produces a method handle giving write access to a static field.
   698          * Access checking is performed immediately on behalf of the lookup class.
   717          * Access checking is performed immediately on behalf of the lookup class.
   699          * @param refc the class or interface from which the method is accessed
   718          * @param refc the class or interface from which the method is accessed
   700          * @param name the field's name
   719          * @param name the field's name
   701          * @param type the field's type
   720          * @param type the field's type
   702          * @return a method handle which can store values into the field
   721          * @return a method handle which can store values into the field
   703          * @exception NoAccessException if access checking fails
   722          * @throws NoSuchFieldException if the field does not exist
   704          */
   723          * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
   705         public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
   724          * @throws NullPointerException if any argument is null
       
   725          */
       
   726         public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
   706             return makeAccessor(refc, name, type, true, true);
   727             return makeAccessor(refc, name, type, true, true);
   707         }
   728         }
   708 
   729 
   709         /**
   730         /**
   710          * Produces an early-bound method handle for a non-static method.
   731          * Produces an early-bound method handle for a non-static method.
   739          * (Note that {@code bindTo} does not preserve variable arity.)
   760          * (Note that {@code bindTo} does not preserve variable arity.)
   740          * @param receiver the object from which the method is accessed
   761          * @param receiver the object from which the method is accessed
   741          * @param name the name of the method
   762          * @param name the name of the method
   742          * @param type the type of the method, with the receiver argument omitted
   763          * @param type the type of the method, with the receiver argument omitted
   743          * @return the desired method handle
   764          * @return the desired method handle
   744          * @exception NoAccessException if the method does not exist or access checking fails
   765          * @throws NoSuchMethodException if the method does not exist
   745          */
   766          * @throws IllegalAccessException if access checking fails
   746         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
   767          * @throws NullPointerException if any argument is null
       
   768          */
       
   769         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
   747             Class<? extends Object> refc = receiver.getClass(); // may get NPE
   770             Class<? extends Object> refc = receiver.getClass(); // may get NPE
   748             MemberName method = resolveOrFail(refc, name, type, false);
   771             MemberName method = resolveOrFail(refc, name, type, false);
   749             checkMethod(refc, method, false);
   772             checkMethod(refc, method, false);
   750             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   773             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   751             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   774             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   752             if (bmh == null)
   775             if (bmh == null)
   753                 throw newNoAccessException(method, lookupClass());
   776                 throw newNoAccessException(method, this);
   754             if (dmh.type().parameterCount() == 0)
   777             if (dmh.type().parameterCount() == 0)
   755                 return dmh;  // bound the trailing parameter; no varargs possible
   778                 return dmh;  // bound the trailing parameter; no varargs possible
   756             return fixVarargs(bmh, dmh);
   779             return fixVarargs(bmh, dmh);
   757         }
   780         }
   758 
   781 
   770          * The returned method handle will have
   793          * The returned method handle will have
   771          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   794          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   772          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   795          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   773          * @param m the reflected method
   796          * @param m the reflected method
   774          * @return a method handle which can invoke the reflected method
   797          * @return a method handle which can invoke the reflected method
   775          * @exception NoAccessException if access checking fails
   798          * @throws IllegalAccessException if access checking fails
   776          */
   799          * @throws NullPointerException if the argument is null
   777         public MethodHandle unreflect(Method m) throws NoAccessException {
   800          */
       
   801         public MethodHandle unreflect(Method m) throws IllegalAccessException {
   778             MemberName method = new MemberName(m);
   802             MemberName method = new MemberName(m);
   779             assert(method.isMethod());
   803             assert(method.isMethod());
   780             if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
   804             if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
   781             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   805             MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
   782             if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
   806             if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
   797          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   821          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   798          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   822          * the method's variable arity modifier bit ({@code 0x0080}) is set.
   799          * @param m the reflected method
   823          * @param m the reflected method
   800          * @param specialCaller the class nominally calling the method
   824          * @param specialCaller the class nominally calling the method
   801          * @return a method handle which can invoke the reflected method
   825          * @return a method handle which can invoke the reflected method
   802          * @exception NoAccessException if access checking fails
   826          * @throws IllegalAccessException if access checking fails
   803          */
   827          * @throws NullPointerException if any argument is null
   804         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
   828          */
       
   829         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
   805             checkSpecialCaller(specialCaller);
   830             checkSpecialCaller(specialCaller);
   806             MemberName method = new MemberName(m);
   831             MemberName method = new MemberName(m);
   807             assert(method.isMethod());
   832             assert(method.isMethod());
   808             // ignore m.isAccessible:  this is a new kind of access
   833             // ignore m.isAccessible:  this is a new kind of access
   809             checkMethod(m.getDeclaringClass(), method, false);
   834             checkMethod(m.getDeclaringClass(), method, false);
   825          * The returned method handle will have
   850          * The returned method handle will have
   826          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   851          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
   827          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
   852          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
   828          * @param c the reflected constructor
   853          * @param c the reflected constructor
   829          * @return a method handle which can invoke the reflected constructor
   854          * @return a method handle which can invoke the reflected constructor
   830          * @exception NoAccessException if access checking fails
   855          * @throws IllegalAccessException if access checking fails
   831          */
   856          * @throws NullPointerException if the argument is null
   832         public MethodHandle unreflectConstructor(Constructor c) throws NoAccessException {
   857          */
       
   858         public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
   833             MemberName ctor = new MemberName(c);
   859             MemberName ctor = new MemberName(c);
   834             assert(ctor.isConstructor());
   860             assert(ctor.isConstructor());
   835             if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
   861             if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
   836             MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
   862             MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
   837             MethodHandle allocator = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
   863             MethodHandle allocator = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
   847          * the field.
   873          * the field.
   848          * If the method's {@code accessible} flag is not set,
   874          * If the method's {@code accessible} flag is not set,
   849          * access checking is performed immediately on behalf of the lookup class.
   875          * access checking is performed immediately on behalf of the lookup class.
   850          * @param f the reflected field
   876          * @param f the reflected field
   851          * @return a method handle which can load values from the reflected field
   877          * @return a method handle which can load values from the reflected field
   852          * @exception NoAccessException if access checking fails
   878          * @throws IllegalAccessException if access checking fails
   853          */
   879          * @throws NullPointerException if the argument is null
   854         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
   880          */
       
   881         public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
   855             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
   882             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
   856         }
   883         }
   857 
   884 
   858         /**
   885         /**
   859          * Produces a method handle giving write access to a reflected field.
   886          * Produces a method handle giving write access to a reflected field.
   864          * the field, and the value to be stored.
   891          * the field, and the value to be stored.
   865          * If the method's {@code accessible} flag is not set,
   892          * If the method's {@code accessible} flag is not set,
   866          * access checking is performed immediately on behalf of the lookup class.
   893          * access checking is performed immediately on behalf of the lookup class.
   867          * @param f the reflected field
   894          * @param f the reflected field
   868          * @return a method handle which can store values into the reflected field
   895          * @return a method handle which can store values into the reflected field
   869          * @exception NoAccessException if access checking fails
   896          * @throws IllegalAccessException if access checking fails
   870          */
   897          * @throws NullPointerException if the argument is null
   871         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
   898          */
       
   899         public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
   872             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
   900             return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
   873         }
   901         }
   874 
   902 
   875         /// Helper methods, all package-private.
   903         /// Helper methods, all package-private.
   876 
   904 
   877         MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
   905         MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException {
   878             checkSymbolicClass(refc);  // do this before attempting to resolve
   906             checkSymbolicClass(refc);  // do this before attempting to resolve
       
   907             name.getClass(); type.getClass();  // NPE
   879             int mods = (isStatic ? Modifier.STATIC : 0);
   908             int mods = (isStatic ? Modifier.STATIC : 0);
   880             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
   909             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
   881         }
   910                                             NoSuchFieldException.class);
   882 
   911         }
   883         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
   912 
       
   913         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException {
   884             checkSymbolicClass(refc);  // do this before attempting to resolve
   914             checkSymbolicClass(refc);  // do this before attempting to resolve
       
   915             name.getClass(); type.getClass();  // NPE
   885             int mods = (isStatic ? Modifier.STATIC : 0);
   916             int mods = (isStatic ? Modifier.STATIC : 0);
   886             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
   917             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
       
   918                                             NoSuchMethodException.class);
   887         }
   919         }
   888 
   920 
   889         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
   921         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
   890                                  boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
   922                                  boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
   891             checkSymbolicClass(refc);  // do this before attempting to resolve
   923             checkSymbolicClass(refc);  // do this before attempting to resolve
       
   924             name.getClass(); type.getClass();  // NPE
   892             int mods = (isStatic ? Modifier.STATIC : 0);
   925             int mods = (isStatic ? Modifier.STATIC : 0);
   893             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
   926             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller,
   894         }
   927                                             NoSuchMethodException.class);
   895 
   928         }
   896         void checkSymbolicClass(Class<?> refc) throws NoAccessException {
   929 
       
   930         void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
   897             Class<?> caller = lookupClassOrNull();
   931             Class<?> caller = lookupClassOrNull();
   898             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
   932             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
   899                 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
   933                 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), this);
   900         }
   934         }
   901 
   935 
   902         void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
   936         void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
   903             String message;
   937             String message;
   904             if (m.isConstructor())
   938             if (m.isConstructor())
   905                 message = "expected a method, not a constructor";
   939                 message = "expected a method, not a constructor";
   906             else if (!m.isMethod())
   940             else if (!m.isMethod())
   907                 message = "expected a method";
   941                 message = "expected a method";
   908             else if (wantStatic != m.isStatic())
   942             else if (wantStatic != m.isStatic())
   909                 message = wantStatic ? "expected a static method" : "expected a non-static method";
   943                 message = wantStatic ? "expected a static method" : "expected a non-static method";
   910             else
   944             else
   911                 { checkAccess(refc, m); return; }
   945                 { checkAccess(refc, m); return; }
   912             throw newNoAccessException(message, m, lookupClass());
   946             throw newNoAccessException(message, m, this);
   913         }
   947         }
   914 
   948 
   915         void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
   949         void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException {
   916             int allowedModes = this.allowedModes;
   950             int allowedModes = this.allowedModes;
   917             if (allowedModes == TRUSTED)  return;
   951             if (allowedModes == TRUSTED)  return;
   918             int mods = m.getModifiers();
   952             int mods = m.getModifiers();
   919             if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
   953             if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
   920                 return;  // common case
   954                 return;  // common case
   925                 return;
   959                 return;
   926             if (((requestedModes & ~allowedModes) & PROTECTED) != 0
   960             if (((requestedModes & ~allowedModes) & PROTECTED) != 0
   927                 && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
   961                 && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
   928                 // Protected members can also be checked as if they were package-private.
   962                 // Protected members can also be checked as if they were package-private.
   929                 return;
   963                 return;
   930             throw newNoAccessException(accessFailedMessage(refc, m), m, lookupClass());
   964             throw newNoAccessException(accessFailedMessage(refc, m), m, this);
   931         }
   965         }
   932 
   966 
   933         String accessFailedMessage(Class<?> refc, MemberName m) {
   967         String accessFailedMessage(Class<?> refc, MemberName m) {
   934             Class<?> defc = m.getDeclaringClass();
   968             Class<?> defc = m.getDeclaringClass();
   935             int mods = m.getModifiers();
   969             int mods = m.getModifiers();
   936             if (!VerifyAccess.isClassAccessible(defc, lookupClass()))
   970             // check the class first:
       
   971             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
       
   972                                (defc == refc ||
       
   973                                 Modifier.isPublic(refc.getModifiers())));
       
   974             if (!classOK && (allowedModes & PACKAGE) != 0) {
       
   975                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) &&
       
   976                            (defc == refc ||
       
   977                             VerifyAccess.isClassAccessible(refc, lookupClass())));
       
   978             }
       
   979             if (!classOK)
   937                 return "class is not public";
   980                 return "class is not public";
   938             if (refc != defc && !VerifyAccess.isClassAccessible(refc, lookupClass()))
       
   939                 return "symbolic reference "+refc.getName()+" is not public";
       
   940             if (Modifier.isPublic(mods))
   981             if (Modifier.isPublic(mods))
   941                 return "access to public member failed";  // (how?)
   982                 return "access to public member failed";  // (how?)
   942             else if (allowedModes == PUBLIC)
       
   943                 return "member is not public";
       
   944             else if (allowedModes == 0)
       
   945                 return "attempted member access through a non-public class";
       
   946             if (Modifier.isPrivate(mods))
   983             if (Modifier.isPrivate(mods))
   947                 return "member is private";
   984                 return "member is private";
   948             if (Modifier.isProtected(mods))
   985             if (Modifier.isProtected(mods))
   949                 return "member is protected";
   986                 return "member is protected";
   950             return "member is private to package";
   987             return "member is private to package";
   951         }
   988         }
   952 
   989 
   953         private static final boolean ALLOW_NESTMATE_ACCESS = false;
   990         private static final boolean ALLOW_NESTMATE_ACCESS = false;
   954 
   991 
   955         void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
   992         void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
   956             if (allowedModes == TRUSTED)  return;
   993             if (allowedModes == TRUSTED)  return;
   957             if ((allowedModes & PRIVATE) == 0
   994             if ((allowedModes & PRIVATE) == 0
   958                 || (specialCaller != lookupClass()
   995                 || (specialCaller != lookupClass()
   959                     && !(ALLOW_NESTMATE_ACCESS &&
   996                     && !(ALLOW_NESTMATE_ACCESS &&
   960                          VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
   997                          VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
   961                 throw newNoAccessException("no private access for invokespecial",
   998                 throw newNoAccessException("no private access for invokespecial",
   962                                            new MemberName(specialCaller), lookupClass());
   999                                            new MemberName(specialCaller), this);
   963         }
  1000         }
   964 
  1001 
   965         MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
  1002         MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
   966             // The accessing class only has the right to use a protected member
  1003             // The accessing class only has the right to use a protected member
   967             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
  1004             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
   968             if (!method.isProtected() || method.isStatic()
  1005             if (!method.isProtected() || method.isStatic()
   969                 || allowedModes == TRUSTED
  1006                 || allowedModes == TRUSTED
   970                 || method.getDeclaringClass() == lookupClass()
  1007                 || method.getDeclaringClass() == lookupClass()
   972                     VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
  1009                     VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
   973                 return mh;
  1010                 return mh;
   974             else
  1011             else
   975                 return restrictReceiver(method, mh, lookupClass());
  1012                 return restrictReceiver(method, mh, lookupClass());
   976         }
  1013         }
   977         MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
  1014         MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
   978             assert(!method.isStatic());
  1015             assert(!method.isStatic());
   979             Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
  1016             Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
   980             if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
  1017             if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
   981                 throw newNoAccessException("caller class must be a subclass below the method", method, caller);
  1018                 throw newNoAccessException("caller class must be a subclass below the method", method, caller);
   982             }
  1019             }
   986             MethodHandle narrowMH = MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
  1023             MethodHandle narrowMH = MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
   987             return fixVarargs(narrowMH, mh);
  1024             return fixVarargs(narrowMH, mh);
   988         }
  1025         }
   989 
  1026 
   990         MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
  1027         MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
   991                                   boolean isStatic, boolean isSetter) throws NoAccessException {
  1028                                   boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
   992             MemberName field = resolveOrFail(refc, name, type, isStatic);
  1029             MemberName field = resolveOrFail(refc, name, type, isStatic);
   993             if (isStatic != field.isStatic())
  1030             if (isStatic != field.isStatic())
   994                 throw newNoAccessException(isStatic
  1031                 throw newNoAccessException(isStatic
   995                                            ? "expected a static field"
  1032                                            ? "expected a static field"
   996                                            : "expected a non-static field",
  1033                                            : "expected a non-static field",
   997                                            field, lookupClass());
  1034                                            field, this);
   998             return makeAccessor(refc, field, false, isSetter);
  1035             return makeAccessor(refc, field, false, isSetter);
   999         }
  1036         }
  1000 
  1037 
  1001         MethodHandle makeAccessor(Class<?> refc, MemberName field,
  1038         MethodHandle makeAccessor(Class<?> refc, MemberName field,
  1002                                   boolean trusted, boolean isSetter) throws NoAccessException {
  1039                                   boolean trusted, boolean isSetter) throws IllegalAccessException {
  1003             assert(field.isField());
  1040             assert(field.isField());
  1004             if (trusted)
  1041             if (trusted)
  1005                 return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
  1042                 return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
  1006             checkAccess(refc, field);
  1043             checkAccess(refc, field);
  1007             MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
  1044             MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());