< prev index next >

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

Print this page




2944          * the {@code Field} object's {@code set} method could return
2945          * normally.  In particular, fields which are both {@code static}
2946          * and {@code final} may never be set.
2947          * <p>
2948          * If the field is {@code static}, and
2949          * if the returned method handle is invoked, the field's class will
2950          * be initialized, if it has not already been initialized.
2951          * @param f the reflected field
2952          * @return a method handle which can store values into the reflected field
2953          * @throws IllegalAccessException if access checking fails,
2954          *         or if the field is {@code final} and write access
2955          *         is not enabled on the {@code Field} object
2956          * @throws NullPointerException if the argument is null
2957          */
2958         public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
2959             return unreflectField(f, true);
2960         }
2961 
2962         private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
2963             MemberName field = new MemberName(f, isSetter);
2964             if (isSetter && field.isStatic() && field.isFinal())

2965                 throw field.makeAccessException("static final field has no write access", this);




2966             assert(isSetter
2967                     ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
2968                     : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
2969             @SuppressWarnings("deprecation")
2970             Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
2971             return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
2972         }
2973 
2974         /**
2975          * Produces a VarHandle giving access to a reflected field {@code f}
2976          * of type {@code T} declared in a class of type {@code R}.
2977          * The VarHandle's variable type is {@code T}.
2978          * If the field is non-static the VarHandle has one coordinate type,
2979          * {@code R}.  Otherwise, the field is static, and the VarHandle has no
2980          * coordinate types.
2981          * <p>
2982          * Access checking is performed immediately on behalf of the lookup
2983          * class, regardless of the value of the field's {@code accessible}
2984          * flag.
2985          * <p>


3506             if (!putField.isFinal()) {
3507                 // A VarHandle does not support updates to final fields, any
3508                 // such VarHandle to a final field will be read-only and
3509                 // therefore the following write-based accessibility checks are
3510                 // only required for non-final fields
3511                 checkField(putRefKind, refc, putField);
3512                 if (checkSecurity)
3513                     checkSecurityManager(refc, putField);
3514             }
3515 
3516             boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
3517                                   restrictProtectedReceiver(getField));
3518             if (doRestrict) {
3519                 assert !getField.isStatic();
3520                 // receiver type of VarHandle is too wide; narrow to caller
3521                 if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
3522                     throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
3523                 }
3524                 refc = lookupClass();
3525             }
3526             return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);

3527         }
3528         /** Check access and get the requested constructor. */
3529         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3530             final boolean checkSecurity = true;
3531             return getDirectConstructorCommon(refc, ctor, checkSecurity);
3532         }
3533         /** Check access and get the requested constructor, eliding security manager checks. */
3534         private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3535             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
3536             return getDirectConstructorCommon(refc, ctor, checkSecurity);
3537         }
3538         /** Common code for all constructors; do not call directly except from immediately above. */
3539         private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
3540                                                   boolean checkSecurity) throws IllegalAccessException {
3541             assert(ctor.isConstructor());
3542             checkAccess(REF_newInvokeSpecial, refc, ctor);
3543             // Optionally check with the security manager; this isn't needed for unreflect* calls.
3544             if (checkSecurity)
3545                 checkSecurityManager(refc, ctor);
3546             assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here




2944          * the {@code Field} object's {@code set} method could return
2945          * normally.  In particular, fields which are both {@code static}
2946          * and {@code final} may never be set.
2947          * <p>
2948          * If the field is {@code static}, and
2949          * if the returned method handle is invoked, the field's class will
2950          * be initialized, if it has not already been initialized.
2951          * @param f the reflected field
2952          * @return a method handle which can store values into the reflected field
2953          * @throws IllegalAccessException if access checking fails,
2954          *         or if the field is {@code final} and write access
2955          *         is not enabled on the {@code Field} object
2956          * @throws NullPointerException if the argument is null
2957          */
2958         public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
2959             return unreflectField(f, true);
2960         }
2961 
2962         private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
2963             MemberName field = new MemberName(f, isSetter);
2964             if (isSetter && field.isFinal()) {
2965                 if (field.isStatic()) {
2966                     throw field.makeAccessException("static final field has no write access", this);
2967                 } else if (field.getDeclaringClass().isHiddenClass()){
2968                     throw field.makeAccessException("final field in a hidden class has no write access", this);
2969                 }
2970             }
2971             assert(isSetter
2972                     ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
2973                     : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
2974             @SuppressWarnings("deprecation")
2975             Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
2976             return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
2977         }
2978 
2979         /**
2980          * Produces a VarHandle giving access to a reflected field {@code f}
2981          * of type {@code T} declared in a class of type {@code R}.
2982          * The VarHandle's variable type is {@code T}.
2983          * If the field is non-static the VarHandle has one coordinate type,
2984          * {@code R}.  Otherwise, the field is static, and the VarHandle has no
2985          * coordinate types.
2986          * <p>
2987          * Access checking is performed immediately on behalf of the lookup
2988          * class, regardless of the value of the field's {@code accessible}
2989          * flag.
2990          * <p>


3511             if (!putField.isFinal()) {
3512                 // A VarHandle does not support updates to final fields, any
3513                 // such VarHandle to a final field will be read-only and
3514                 // therefore the following write-based accessibility checks are
3515                 // only required for non-final fields
3516                 checkField(putRefKind, refc, putField);
3517                 if (checkSecurity)
3518                     checkSecurityManager(refc, putField);
3519             }
3520 
3521             boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
3522                                   restrictProtectedReceiver(getField));
3523             if (doRestrict) {
3524                 assert !getField.isStatic();
3525                 // receiver type of VarHandle is too wide; narrow to caller
3526                 if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
3527                     throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
3528                 }
3529                 refc = lookupClass();
3530             }
3531             return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(),
3532                                              this.allowedModes == TRUSTED && !getField.getDeclaringClass().isHiddenClass());
3533         }
3534         /** Check access and get the requested constructor. */
3535         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3536             final boolean checkSecurity = true;
3537             return getDirectConstructorCommon(refc, ctor, checkSecurity);
3538         }
3539         /** Check access and get the requested constructor, eliding security manager checks. */
3540         private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
3541             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
3542             return getDirectConstructorCommon(refc, ctor, checkSecurity);
3543         }
3544         /** Common code for all constructors; do not call directly except from immediately above. */
3545         private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
3546                                                   boolean checkSecurity) throws IllegalAccessException {
3547             assert(ctor.isConstructor());
3548             checkAccess(REF_newInvokeSpecial, refc, ctor);
3549             // Optionally check with the security manager; this isn't needed for unreflect* calls.
3550             if (checkSecurity)
3551                 checkSecurityManager(refc, ctor);
3552             assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here


< prev index next >