< 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 — 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 >