3428 * @throws IllegalAccessException if access checking fails,
3429 * or if the field is {@code final} and write access
3430 * is not enabled on the {@code Field} object
3431 * @throws NullPointerException if the argument is null
3432 * @see <a href="{@docRoot}/java.base/java/lang/reflect/doc-files/MutationMethods.html">Mutation methods</a>
3433 */
3434 public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
3435 return unreflectField(f, true);
3436 }
3437
3438 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
3439 @SuppressWarnings("deprecation")
3440 boolean isAccessible = f.isAccessible();
3441 MemberName field = new MemberName(f, isSetter);
3442 if (isSetter && field.isFinal()) {
3443 if (field.isTrustedFinalField()) {
3444 String msg = field.isStatic() ? "static final field has no write access"
3445 : "final field has no write access";
3446 throw field.makeAccessException(msg, this);
3447 }
3448 // check if write access to final field allowed
3449 if (!field.isStatic() && isAccessible) {
3450 SharedSecrets.getJavaLangReflectAccess().checkAllowedToUnreflectFinalSetter(lookupClass, f);
3451 }
3452 }
3453 assert(isSetter
3454 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
3455 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
3456 Lookup lookup = isAccessible ? IMPL_LOOKUP : this;
3457 return lookup.getDirectField(field.getReferenceKind(), f.getDeclaringClass(), field);
3458 }
3459
3460 /**
3461 * Produces a VarHandle giving access to a reflected field {@code f}
3462 * of type {@code T} declared in a class of type {@code R}.
3463 * The VarHandle's variable type is {@code T}.
3464 * If the field is non-static the VarHandle has one coordinate type,
3465 * {@code R}. Otherwise, the field is static, and the VarHandle has no
3466 * coordinate types.
3467 * <p>
3944
3945 if (!putField.isFinal()) {
3946 // A VarHandle does not support updates to final fields, any
3947 // such VarHandle to a final field will be read-only and
3948 // therefore the following write-based accessibility checks are
3949 // only required for non-final fields
3950 checkField(putRefKind, refc, putField);
3951 }
3952
3953 boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
3954 restrictProtectedReceiver(getField));
3955 if (doRestrict) {
3956 assert !getField.isStatic();
3957 // receiver type of VarHandle is too wide; narrow to caller
3958 if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
3959 throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
3960 }
3961 refc = lookupClass();
3962 }
3963 return VarHandles.makeFieldHandle(getField, refc,
3964 this.allowedModes == TRUSTED && !getField.isTrustedFinalField());
3965 }
3966 /** Check access and get the requested constructor. */
3967 private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3968 return getDirectConstructorCommon(refc, ctor);
3969 }
3970 /** Common code for all constructors; do not call directly except from immediately above. */
3971 private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3972 assert(ctor.isConstructor());
3973 checkAccess(REF_newInvokeSpecial, refc, ctor);
3974 assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here
3975 return DirectMethodHandle.make(ctor).setVarargs(ctor);
3976 }
3977
3978 /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
3979 */
3980 /*non-public*/
3981 MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type)
3982 throws ReflectiveOperationException {
3983 if (!(type instanceof Class || type instanceof MethodType))
3984 throw new InternalError("unresolved MemberName");
|
3428 * @throws IllegalAccessException if access checking fails,
3429 * or if the field is {@code final} and write access
3430 * is not enabled on the {@code Field} object
3431 * @throws NullPointerException if the argument is null
3432 * @see <a href="{@docRoot}/java.base/java/lang/reflect/doc-files/MutationMethods.html">Mutation methods</a>
3433 */
3434 public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
3435 return unreflectField(f, true);
3436 }
3437
3438 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
3439 @SuppressWarnings("deprecation")
3440 boolean isAccessible = f.isAccessible();
3441 MemberName field = new MemberName(f, isSetter);
3442 if (isSetter && field.isFinal()) {
3443 if (field.isTrustedFinalField()) {
3444 String msg = field.isStatic() ? "static final field has no write access"
3445 : "final field has no write access";
3446 throw field.makeAccessException(msg, this);
3447 }
3448 // strictly-initialized finals not trusted finals at this time
3449 if (field.isStrictInit()) {
3450 throw field.makeAccessException("strictly-initialized final field has no write access", this);
3451 }
3452
3453 // check if write access to final field allowed
3454 if (!field.isStatic() && isAccessible) {
3455 SharedSecrets.getJavaLangReflectAccess().checkAllowedToUnreflectFinalSetter(lookupClass, f);
3456 }
3457 }
3458 assert(isSetter
3459 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
3460 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
3461 Lookup lookup = isAccessible ? IMPL_LOOKUP : this;
3462 return lookup.getDirectField(field.getReferenceKind(), f.getDeclaringClass(), field);
3463 }
3464
3465 /**
3466 * Produces a VarHandle giving access to a reflected field {@code f}
3467 * of type {@code T} declared in a class of type {@code R}.
3468 * The VarHandle's variable type is {@code T}.
3469 * If the field is non-static the VarHandle has one coordinate type,
3470 * {@code R}. Otherwise, the field is static, and the VarHandle has no
3471 * coordinate types.
3472 * <p>
3949
3950 if (!putField.isFinal()) {
3951 // A VarHandle does not support updates to final fields, any
3952 // such VarHandle to a final field will be read-only and
3953 // therefore the following write-based accessibility checks are
3954 // only required for non-final fields
3955 checkField(putRefKind, refc, putField);
3956 }
3957
3958 boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
3959 restrictProtectedReceiver(getField));
3960 if (doRestrict) {
3961 assert !getField.isStatic();
3962 // receiver type of VarHandle is too wide; narrow to caller
3963 if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
3964 throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
3965 }
3966 refc = lookupClass();
3967 }
3968 return VarHandles.makeFieldHandle(getField, refc,
3969 this.allowedModes == TRUSTED);
3970 }
3971 /** Check access and get the requested constructor. */
3972 private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3973 return getDirectConstructorCommon(refc, ctor);
3974 }
3975 /** Common code for all constructors; do not call directly except from immediately above. */
3976 private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3977 assert(ctor.isConstructor());
3978 checkAccess(REF_newInvokeSpecial, refc, ctor);
3979 assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here
3980 return DirectMethodHandle.make(ctor).setVarargs(ctor);
3981 }
3982
3983 /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
3984 */
3985 /*non-public*/
3986 MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type)
3987 throws ReflectiveOperationException {
3988 if (!(type instanceof Class || type instanceof MethodType))
3989 throw new InternalError("unresolved MemberName");
|