< prev index next >

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

Print this page

        

*** 420,429 **** --- 420,433 ---- * A lookup can fail, because * the containing class is not accessible to the lookup class, or * because the desired class member is missing, or because the * desired class member is not accessible to the lookup class, or * because the lookup object is not trusted enough to access the member. + * In the case of a field setter function on a {@code final} field, + * finality enforcement is treated as a kind of access control, + * and the lookup will fail, except in special cases of + * {@link Lookup#unreflectSetter Lookup.unreflectSetter}. * In any of these cases, a {@code ReflectiveOperationException} will be * thrown from the attempted lookup. The exact class will be one of * the following: * <ul> * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
*** 1436,1445 **** --- 1440,1450 ---- * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field * @throws NoSuchFieldException if the field does not exist * @throws IllegalAccessException if access checking fails, or if the field is {@code static} + * or {@code final} * @exception SecurityException if a security manager is present and it * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * @throws NullPointerException if any argument is null * @see #findVarHandle(Class, String, Class) */
*** 1559,1568 **** --- 1564,1574 ---- * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field * @throws NoSuchFieldException if the field does not exist * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} + * or is {@code final} * @exception SecurityException if a security manager is present and it * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * @throws NullPointerException if any argument is null */ public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
*** 1838,1851 **** /** * Produces a method handle giving read access to a reflected field. * The type of the method handle will have a return type of the field's * value type. ! * If the field is static, the method handle will take no arguments. * Otherwise, its single argument will be the instance containing * the field. ! * If the field's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * <p> * If the field is static, and * if the returned method handle is invoked, the field's class will * be initialized, if it has not already been initialized. --- 1844,1857 ---- /** * Produces a method handle giving read access to a reflected field. * The type of the method handle will have a return type of the field's * value type. ! * If the field is {@code static}, the method handle will take no arguments. * Otherwise, its single argument will be the instance containing * the field. ! * If the {@code Field} object's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * <p> * If the field is static, and * if the returned method handle is invoked, the field's class will * be initialized, if it has not already been initialized.
*** 1855,1896 **** * @throws NullPointerException if the argument is null */ public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { return unreflectField(f, false); } - private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { - MemberName field = new MemberName(f, isSetter); - assert(isSetter - ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) - : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); - @SuppressWarnings("deprecation") - Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); - } /** * Produces a method handle giving write access to a reflected field. * The type of the method handle will have a void return type. ! * If the field is static, the method handle will take a single * argument, of the field's value type, the value to be stored. * Otherwise, the two arguments will be the instance containing * the field, and the value to be stored. ! * If the field's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * <p> ! * If the field is static, and * if the returned method handle is invoked, the field's class will * be initialized, if it has not already been initialized. * @param f the reflected field * @return a method handle which can store values into the reflected field ! * @throws IllegalAccessException if access checking fails * @throws NullPointerException if the argument is null */ public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { return unreflectField(f, true); } /** * Produces a VarHandle giving access to a reflected field {@code f} * of type {@code T} declared in a class of type {@code R}. * The VarHandle's variable type is {@code T}. * If the field is non-static the VarHandle has one coordinate type, --- 1861,1915 ---- * @throws NullPointerException if the argument is null */ public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { return unreflectField(f, false); } /** * Produces a method handle giving write access to a reflected field. * The type of the method handle will have a void return type. ! * If the field is {@code static}, the method handle will take a single * argument, of the field's value type, the value to be stored. * Otherwise, the two arguments will be the instance containing * the field, and the value to be stored. ! * If the {@code Field} object's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * <p> ! * If the field is {@code final}, write access will not be ! * allowed and access checking will fail, except under certain ! * narrow circumstances documented for {@link Field#set Field.set}. ! * A method handle is returned only if a corresponding call to ! * the {@code Field} object's {@code set} method could return ! * normally. In particular, fields which are both {@code static} ! * and {@code final} may never be set. ! * <p> ! * If the field is {@code static}, and * if the returned method handle is invoked, the field's class will * be initialized, if it has not already been initialized. * @param f the reflected field * @return a method handle which can store values into the reflected field ! * @throws IllegalAccessException if access checking fails, ! * or if the field is {@code final} and write access ! * is not enabled on the {@code Field} object * @throws NullPointerException if the argument is null */ public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { return unreflectField(f, true); } + private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { + MemberName field = new MemberName(f, isSetter); + if (isSetter && field.isStatic() && field.isFinal()) + throw field.makeAccessException("static final field has no write access", this); + assert(isSetter + ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) + : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); + @SuppressWarnings("deprecation") + Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; + return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); + } + /** * Produces a VarHandle giving access to a reflected field {@code f} * of type {@code T} declared in a class of type {@code R}. * The VarHandle's variable type is {@code T}. * If the field is non-static the VarHandle has one coordinate type,
< prev index next >