< prev index next >

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

Print this page




 405      * All access checks start from a {@code Lookup} object, which
 406      * compares its recorded lookup class against all requests to
 407      * create method handles.
 408      * A single {@code Lookup} object can be used to create any number
 409      * of access-checked method handles, all checked against a single
 410      * lookup class.
 411      * <p>
 412      * A {@code Lookup} object can be shared with other trusted code,
 413      * such as a metaobject protocol.
 414      * A shared {@code Lookup} object delegates the capability
 415      * to create method handles on private members of the lookup class.
 416      * Even if privileged code uses the {@code Lookup} object,
 417      * the access checking is confined to the privileges of the
 418      * original lookup class.
 419      * <p>
 420      * A lookup can fail, because
 421      * the containing class is not accessible to the lookup class, or
 422      * because the desired class member is missing, or because the
 423      * desired class member is not accessible to the lookup class, or
 424      * because the lookup object is not trusted enough to access the member.




 425      * In any of these cases, a {@code ReflectiveOperationException} will be
 426      * thrown from the attempted lookup.  The exact class will be one of
 427      * the following:
 428      * <ul>
 429      * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
 430      * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
 431      * <li>IllegalAccessException &mdash; if the member exists but an access check fails
 432      * </ul>
 433      * <p>
 434      * In general, the conditions under which a method handle may be
 435      * looked up for a method {@code M} are no more restrictive than the conditions
 436      * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
 437      * Where the JVM would raise exceptions like {@code NoSuchMethodError},
 438      * a method handle lookup will generally raise a corresponding
 439      * checked exception, such as {@code NoSuchMethodException}.
 440      * And the effect of invoking the method handle resulting from the lookup
 441      * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
 442      * to executing the compiled, verified, and resolved call to {@code M}.
 443      * The same point is true of fields and constructors.
 444      * <p style="font-size:smaller;">


1421          * @see #findVarHandle(Class, String, Class)
1422          */
1423         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1424             MemberName field = resolveOrFail(REF_getField, refc, name, type);
1425             return getDirectField(REF_getField, refc, field);
1426         }
1427 
1428         /**
1429          * Produces a method handle giving write access to a non-static field.
1430          * The type of the method handle will have a void return type.
1431          * The method handle will take two arguments, the instance containing
1432          * the field, and the value to be stored.
1433          * The second argument will be of the field's value type.
1434          * Access checking is performed immediately on behalf of the lookup class.
1435          * @param refc the class or interface from which the method is accessed
1436          * @param name the field's name
1437          * @param type the field's type
1438          * @return a method handle which can store values into the field
1439          * @throws NoSuchFieldException if the field does not exist
1440          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}

1441          * @exception SecurityException if a security manager is present and it
1442          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1443          * @throws NullPointerException if any argument is null
1444          * @see #findVarHandle(Class, String, Class)
1445          */
1446         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1447             MemberName field = resolveOrFail(REF_putField, refc, name, type);
1448             return getDirectField(REF_putField, refc, field);
1449         }
1450 
1451         /**
1452          * Produces a VarHandle giving access to a non-static field {@code name}
1453          * of type {@code type} declared in a class of type {@code recv}.
1454          * The VarHandle's variable type is {@code type} and it has one
1455          * coordinate type, {@code recv}.
1456          * <p>
1457          * Access checking is performed immediately on behalf of the lookup
1458          * class.
1459          * <p>
1460          * Certain access modes of the returned VarHandle are unsupported under


1544         public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1545             MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
1546             return getDirectField(REF_getStatic, refc, field);
1547         }
1548 
1549         /**
1550          * Produces a method handle giving write access to a static field.
1551          * The type of the method handle will have a void return type.
1552          * The method handle will take a single
1553          * argument, of the field's value type, the value to be stored.
1554          * Access checking is performed immediately on behalf of the lookup class.
1555          * <p>
1556          * If the returned method handle is invoked, the field's class will
1557          * be initialized, if it has not already been initialized.
1558          * @param refc the class or interface from which the method is accessed
1559          * @param name the field's name
1560          * @param type the field's type
1561          * @return a method handle which can store values into the field
1562          * @throws NoSuchFieldException if the field does not exist
1563          * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}

1564          * @exception SecurityException if a security manager is present and it
1565          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1566          * @throws NullPointerException if any argument is null
1567          */
1568         public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1569             MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
1570             return getDirectField(REF_putStatic, refc, field);
1571         }
1572 
1573         /**
1574          * Produces a VarHandle giving access to a static field {@code name} of
1575          * type {@code type} declared in a class of type {@code decl}.
1576          * The VarHandle's variable type is {@code type} and it has no
1577          * coordinate types.
1578          * <p>
1579          * Access checking is performed immediately on behalf of the lookup
1580          * class.
1581          * <p>
1582          * If the returned VarHandle is operated on, the declaring class will be
1583          * initialized, if it has not already been initialized.


1823          * be initialized, if it has not already been initialized.
1824          * @param c the reflected constructor
1825          * @return a method handle which can invoke the reflected constructor
1826          * @throws IllegalAccessException if access checking fails
1827          *                                or if the method's variable arity modifier bit
1828          *                                is set and {@code asVarargsCollector} fails
1829          * @throws NullPointerException if the argument is null
1830          */
1831         public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
1832             MemberName ctor = new MemberName(c);
1833             assert(ctor.isConstructor());
1834             @SuppressWarnings("deprecation")
1835             Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
1836             return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
1837         }
1838 
1839         /**
1840          * Produces a method handle giving read access to a reflected field.
1841          * The type of the method handle will have a return type of the field's
1842          * value type.
1843          * If the field is static, the method handle will take no arguments.
1844          * Otherwise, its single argument will be the instance containing
1845          * the field.
1846          * If the field's {@code accessible} flag is not set,
1847          * access checking is performed immediately on behalf of the lookup class.
1848          * <p>
1849          * If the field is static, and
1850          * if the returned method handle is invoked, the field's class will
1851          * be initialized, if it has not already been initialized.
1852          * @param f the reflected field
1853          * @return a method handle which can load values from the reflected field
1854          * @throws IllegalAccessException if access checking fails
1855          * @throws NullPointerException if the argument is null
1856          */
1857         public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
1858             return unreflectField(f, false);
1859         }
1860         private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
1861             MemberName field = new MemberName(f, isSetter);
1862             assert(isSetter
1863                     ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
1864                     : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));



1865             @SuppressWarnings("deprecation")
1866             Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
1867             return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
1868         }
1869 
1870         /**
1871          * Produces a method handle giving write access to a reflected field.
1872          * The type of the method handle will have a void return type.
1873          * If the field is static, the method handle will take a single
1874          * argument, of the field's value type, the value to be stored.
1875          * Otherwise, the two arguments will be the instance containing
1876          * the field, and the value to be stored.
1877          * If the field's {@code accessible} flag is not set,
1878          * access checking is performed immediately on behalf of the lookup class.
1879          * <p>
1880          * If the field is static, and








1881          * if the returned method handle is invoked, the field's class will
1882          * be initialized, if it has not already been initialized.
1883          * @param f the reflected field
1884          * @return a method handle which can store values into the reflected field
1885          * @throws IllegalAccessException if access checking fails


1886          * @throws NullPointerException if the argument is null
1887          */
1888         public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
1889             return unreflectField(f, true);
1890         }
1891 
1892         /**
1893          * Produces a VarHandle giving access to a reflected field {@code f}
1894          * of type {@code T} declared in a class of type {@code R}.
1895          * The VarHandle's variable type is {@code T}.
1896          * If the field is non-static the VarHandle has one coordinate type,
1897          * {@code R}.  Otherwise, the field is static, and the VarHandle has no
1898          * coordinate types.
1899          * <p>
1900          * Access checking is performed immediately on behalf of the lookup
1901          * class, regardless of the value of the field's {@code accessible}
1902          * flag.
1903          * <p>
1904          * If the field is static, and if the returned VarHandle is operated
1905          * on, the field's declaring class will be initialized, if it has not




 405      * All access checks start from a {@code Lookup} object, which
 406      * compares its recorded lookup class against all requests to
 407      * create method handles.
 408      * A single {@code Lookup} object can be used to create any number
 409      * of access-checked method handles, all checked against a single
 410      * lookup class.
 411      * <p>
 412      * A {@code Lookup} object can be shared with other trusted code,
 413      * such as a metaobject protocol.
 414      * A shared {@code Lookup} object delegates the capability
 415      * to create method handles on private members of the lookup class.
 416      * Even if privileged code uses the {@code Lookup} object,
 417      * the access checking is confined to the privileges of the
 418      * original lookup class.
 419      * <p>
 420      * A lookup can fail, because
 421      * the containing class is not accessible to the lookup class, or
 422      * because the desired class member is missing, or because the
 423      * desired class member is not accessible to the lookup class, or
 424      * because the lookup object is not trusted enough to access the member.
 425      * In the case of a field setter function on a {@code final} field,
 426      * finality enforcement is treated as a kind of access control,
 427      * and the lookup will fail, except in special cases of
 428      * {@link Lookup#unreflectSetter Lookup.unreflectSetter}.
 429      * In any of these cases, a {@code ReflectiveOperationException} will be
 430      * thrown from the attempted lookup.  The exact class will be one of
 431      * the following:
 432      * <ul>
 433      * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
 434      * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
 435      * <li>IllegalAccessException &mdash; if the member exists but an access check fails
 436      * </ul>
 437      * <p>
 438      * In general, the conditions under which a method handle may be
 439      * looked up for a method {@code M} are no more restrictive than the conditions
 440      * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
 441      * Where the JVM would raise exceptions like {@code NoSuchMethodError},
 442      * a method handle lookup will generally raise a corresponding
 443      * checked exception, such as {@code NoSuchMethodException}.
 444      * And the effect of invoking the method handle resulting from the lookup
 445      * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
 446      * to executing the compiled, verified, and resolved call to {@code M}.
 447      * The same point is true of fields and constructors.
 448      * <p style="font-size:smaller;">


1425          * @see #findVarHandle(Class, String, Class)
1426          */
1427         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1428             MemberName field = resolveOrFail(REF_getField, refc, name, type);
1429             return getDirectField(REF_getField, refc, field);
1430         }
1431 
1432         /**
1433          * Produces a method handle giving write access to a non-static field.
1434          * The type of the method handle will have a void return type.
1435          * The method handle will take two arguments, the instance containing
1436          * the field, and the value to be stored.
1437          * The second argument will be of the field's value type.
1438          * Access checking is performed immediately on behalf of the lookup class.
1439          * @param refc the class or interface from which the method is accessed
1440          * @param name the field's name
1441          * @param type the field's type
1442          * @return a method handle which can store values into the field
1443          * @throws NoSuchFieldException if the field does not exist
1444          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1445          * or {@code final}
1446          * @exception SecurityException if a security manager is present and it
1447          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1448          * @throws NullPointerException if any argument is null
1449          * @see #findVarHandle(Class, String, Class)
1450          */
1451         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1452             MemberName field = resolveOrFail(REF_putField, refc, name, type);
1453             return getDirectField(REF_putField, refc, field);
1454         }
1455 
1456         /**
1457          * Produces a VarHandle giving access to a non-static field {@code name}
1458          * of type {@code type} declared in a class of type {@code recv}.
1459          * The VarHandle's variable type is {@code type} and it has one
1460          * coordinate type, {@code recv}.
1461          * <p>
1462          * Access checking is performed immediately on behalf of the lookup
1463          * class.
1464          * <p>
1465          * Certain access modes of the returned VarHandle are unsupported under


1549         public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1550             MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
1551             return getDirectField(REF_getStatic, refc, field);
1552         }
1553 
1554         /**
1555          * Produces a method handle giving write access to a static field.
1556          * The type of the method handle will have a void return type.
1557          * The method handle will take a single
1558          * argument, of the field's value type, the value to be stored.
1559          * Access checking is performed immediately on behalf of the lookup class.
1560          * <p>
1561          * If the returned method handle is invoked, the field's class will
1562          * be initialized, if it has not already been initialized.
1563          * @param refc the class or interface from which the method is accessed
1564          * @param name the field's name
1565          * @param type the field's type
1566          * @return a method handle which can store values into the field
1567          * @throws NoSuchFieldException if the field does not exist
1568          * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
1569          * or is {@code final}
1570          * @exception SecurityException if a security manager is present and it
1571          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1572          * @throws NullPointerException if any argument is null
1573          */
1574         public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1575             MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
1576             return getDirectField(REF_putStatic, refc, field);
1577         }
1578 
1579         /**
1580          * Produces a VarHandle giving access to a static field {@code name} of
1581          * type {@code type} declared in a class of type {@code decl}.
1582          * The VarHandle's variable type is {@code type} and it has no
1583          * coordinate types.
1584          * <p>
1585          * Access checking is performed immediately on behalf of the lookup
1586          * class.
1587          * <p>
1588          * If the returned VarHandle is operated on, the declaring class will be
1589          * initialized, if it has not already been initialized.


1829          * be initialized, if it has not already been initialized.
1830          * @param c the reflected constructor
1831          * @return a method handle which can invoke the reflected constructor
1832          * @throws IllegalAccessException if access checking fails
1833          *                                or if the method's variable arity modifier bit
1834          *                                is set and {@code asVarargsCollector} fails
1835          * @throws NullPointerException if the argument is null
1836          */
1837         public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
1838             MemberName ctor = new MemberName(c);
1839             assert(ctor.isConstructor());
1840             @SuppressWarnings("deprecation")
1841             Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
1842             return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
1843         }
1844 
1845         /**
1846          * Produces a method handle giving read access to a reflected field.
1847          * The type of the method handle will have a return type of the field's
1848          * value type.
1849          * If the field is {@code static}, the method handle will take no arguments.
1850          * Otherwise, its single argument will be the instance containing
1851          * the field.
1852          * If the {@code Field} object's {@code accessible} flag is not set,
1853          * access checking is performed immediately on behalf of the lookup class.
1854          * <p>
1855          * If the field is static, and
1856          * if the returned method handle is invoked, the field's class will
1857          * be initialized, if it has not already been initialized.
1858          * @param f the reflected field
1859          * @return a method handle which can load values from the reflected field
1860          * @throws IllegalAccessException if access checking fails
1861          * @throws NullPointerException if the argument is null
1862          */
1863         public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
1864             return unreflectField(f, false);
1865         }
1866         private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
1867             MemberName field = new MemberName(f, isSetter);
1868             assert(isSetter
1869                     ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
1870                     : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
1871             if (isSetter && field.isStatic() && field.isFinal()) {
1872                 throw field.makeAccessException("static final field has no write access", this);
1873             }
1874             @SuppressWarnings("deprecation")
1875             Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
1876             return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
1877         }
1878 
1879         /**
1880          * Produces a method handle giving write access to a reflected field.
1881          * The type of the method handle will have a void return type.
1882          * If the field is {@code static}, the method handle will take a single
1883          * argument, of the field's value type, the value to be stored.
1884          * Otherwise, the two arguments will be the instance containing
1885          * the field, and the value to be stored.
1886          * If the {@code Field} object's {@code accessible} flag is not set,
1887          * access checking is performed immediately on behalf of the lookup class.
1888          * <p>
1889          * If the field is {@code final}, write access will not be
1890          * allowed and access checking will fail, except under certain
1891          * narrow circumstances documented for {@link Field#set Field.set}.
1892          * A method handle is returned only if a corresponding call to
1893          * the {@code Field} object's {@code set} method could return
1894          * normally. In particular, fields which are both {@code static}
1895          * and {@code final} may never be set.
1896          * <p>
1897          * If the field is {@code static}, and
1898          * if the returned method handle is invoked, the field's class will
1899          * be initialized, if it has not already been initialized.
1900          * @param f the reflected field
1901          * @return a method handle which can store values into the reflected field
1902          * @throws IllegalAccessException if access checking fails,
1903          * or if the field is {@code final} and write access
1904          * is not enabled on the {@code Field} object
1905          * @throws NullPointerException if the argument is null
1906          */
1907         public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
1908             return unreflectField(f, true);
1909         }
1910 
1911         /**
1912          * Produces a VarHandle giving access to a reflected field {@code f}
1913          * of type {@code T} declared in a class of type {@code R}.
1914          * The VarHandle's variable type is {@code T}.
1915          * If the field is non-static the VarHandle has one coordinate type,
1916          * {@code R}.  Otherwise, the field is static, and the VarHandle has no
1917          * coordinate types.
1918          * <p>
1919          * Access checking is performed immediately on behalf of the lookup
1920          * class, regardless of the value of the field's {@code accessible}
1921          * flag.
1922          * <p>
1923          * If the field is static, and if the returned VarHandle is operated
1924          * on, the field's declaring class will be initialized, if it has not


< prev index next >