mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8216558: Lookup.unreflectSetter(Field) fails to throw IllegalAccessException for final fields
Reviewed-by: mchung
This commit is contained in:
parent
4df14bb14b
commit
be132fcc65
4 changed files with 114 additions and 56 deletions
|
@ -422,6 +422,10 @@ public class MethodHandles {
|
|||
* 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:
|
||||
|
@ -1438,6 +1442,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
|||
* @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
|
||||
|
@ -1561,6 +1566,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
|||
* @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
|
||||
|
@ -1840,10 +1846,10 @@ return mh1;
|
|||
* 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.
|
||||
* 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 field's {@code accessible} flag is not set,
|
||||
* 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
|
||||
|
@ -1857,8 +1863,43 @@ return mh1;
|
|||
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()));
|
||||
|
@ -1867,28 +1908,6 @@ return mh1;
|
|||
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}.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue