On Mon, 15 Jun 2026 13:44:56 GMT, Chen Liang <[email protected]> wrote:
>> Using the reflection APIs to mutate a strictly-initialized final instance >> field should fail with IllegalAccessException. >> >> The list of conditions in Field.set and setAccessible are also updated. >> >> --------- >> - [x] I confirm that I make this contribution in accordance with the >> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai). > > src/java.base/share/classes/java/lang/reflect/Field.java line 193: > >> 191: * <li>final fields declared in a {@linkplain Class#isRecord() >> record}</li> >> 192: * <li>final fields declared in a {@linkplain Class#isHidden() >> hidden class}</li> >> 193: * <li>{@linkplain #isStrictInit() strictly-initialized} final >> fields</li> > > The other examples from identity requirements use a preview block, or as in > `SwitchBootstraps`, prefixed with "if preview features are enabled, ..." This is a list of conditions and the "strictly-initialized" will have "PREVIEW" superscript. So it's like Field.set which links to value class with the "PREVIEW" superscript. I think it looks okay but I agree some prefixing with "if preview features" might be a bit clearer. > src/java.base/share/classes/java/lang/reflect/Field.java line 1527: > >> 1525: >> 1526: // strictly-initialized final fields cannot be mutated >> 1527: if (isStrictInit()) { > > I think the check is best done here, which should fix all MethodHandle too: > https://github.com/AlanBateman/valhalla/blob/1890ec9eb8038d92f5fba3107085cafabdc9f21e/src/java.base/share/classes/java/lang/invoke/MethodHandles.java#L3443 This is a good question. We went around this a few times during JEP 500 and decided to send the conditional cases through checkAllowedToUnreflectFinalSetter, the benefit being that everything related to the CLI options to allow mutation of finals is in one place. You are right that the strict final fields case can't be changed by the CLI options so isStrictInit can be checked eariler. It means that newFieldAccessor must be created without a setter, which is a good thing. > test/jdk/java/lang/reflect/Field/StrictInitFinalFields.java line 135: > >> 133: VarHandle vh = lookup.unreflectVarHandle(field); >> 134: assertEquals(initialValue, vh.get(obj)); >> 135: assertThrows(UnsupportedOperationException.class, () -> >> vh.set(obj, newValue)); > > Luckily VarHandle already rejects all final fields, as I last checked in JEP > 500 - it has some problem with non-final strict-init, addressed in #2550. Yes, VarHandle doesn't allow it. This test is checking Field.set behavior and then unreflects to test method handle and VarHandle behavior too. I think that is okay to test here. ------------- PR Review Comment: https://git.openjdk.org/valhalla/pull/2548#discussion_r3414664149 PR Review Comment: https://git.openjdk.org/valhalla/pull/2548#discussion_r3414650631 PR Review Comment: https://git.openjdk.org/valhalla/pull/2548#discussion_r3415792730
