< prev index next > src/java.base/share/classes/java/lang/reflect/Field.java
Print this page
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import jdk.internal.access.SharedSecrets;
import jdk.internal.event.FinalFieldMutationEvent;
+ import jdk.internal.javac.PreviewFeature;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.Modules;
+ import jdk.internal.reflect.AccessFlagSet;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.FieldAccessor;
+ import jdk.internal.reflect.PreviewAccessFlags;
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.generics.repository.FieldRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation
private final String name;
private final Class<?> type;
private final int modifiers;
- private final boolean trustedFinal;
+ private final int flags;
// Generics and annotations support
private final transient String signature;
private final byte[] annotations;
/**
@SuppressWarnings("deprecation")
Field(Class<?> declaringClass,
String name,
Class<?> type,
int modifiers,
- boolean trustedFinal,
+ int flags,
int slot,
String signature,
byte[] annotations)
{
this.clazz = declaringClass;
this.name = name;
this.type = type;
this.modifiers = modifiers;
- this.trustedFinal = trustedFinal;
+ this.flags = flags;
this.slot = slot;
this.signature = signature;
this.annotations = annotations;
}
// objects be fabricated for each reflective call on Class
// objects.)
if (this.root != null)
throw new IllegalArgumentException("Can not copy a non-root Field");
- Field res = new Field(clazz, name, type, modifiers, trustedFinal, slot, signature, annotations);
+ Field res = new Field(clazz, name, type, modifiers, flags, slot, signature, annotations);
res.root = this;
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
res.overrideFieldAccessor = overrideFieldAccessor;
res.genericInfo = genericInfo;
* IllegalAccessException}. The following fields are non-modifiable:
* <ul>
* <li>static final fields declared in any class or interface</li>
* <li>final fields declared in a {@linkplain Class#isRecord() record}</li>
* <li>final fields declared in a {@linkplain Class#isHidden() hidden class}</li>
+ * <li>fields declared in a {@linkplain Class#isValue() value class}</li>
+ * <li>{@linkplain #isStrictInit() strictly-initialized} final fields</li>
* </ul>
- * <p>If this reflected object represents a non-static final field in a class that
- * is not a record class or hidden class, then enabling access will enable read
- * access. Whether write access is allowed or not is checked when attempting to
- * {@linkplain #set(Object, Object) set} the field value.
+ * <p>Final fields that are not covered by this list may be <em>modifiable</em>.
+ * Enabling access will enable read access. Whether write access is allowed is
+ * checked when attempting to {@linkplain #set(Object, Object) set} the field value.
*
* @throws InaccessibleObjectException {@inheritDoc}
*/
@Override
@CallerSensitive
* @jvms 4.5 Fields
* @since 20
*/
@Override
public Set<AccessFlag> accessFlags() {
- return reflectionFactory.parseAccessFlags(getModifiers(), AccessFlag.Location.FIELD, getDeclaringClass());
+ return AccessFlagSet.ofValidated(PreviewAccessFlags.FIELD_PREVIEW_FLAGS, getModifiers());
}
/**
* Returns {@code true} if this field represents an element of
* an enumerated class; returns {@code false} otherwise.
*/
public boolean isSynthetic() {
return Modifier.isSynthetic(getModifiers());
}
+ /**
+ * Returns {@code true} if this field is a strictly-initialized field;
+ * returns {@code false} otherwise.
+ *
+ * <p>This method returns {@code true} if and only if the class or interface
+ * that declares this field uses preview features and this field is a
+ * strictly-initialized field. The {@link AccessFlag#STRICT_INIT
+ * ACC_STRICT_INIT} flag is considered not set for a field declared in a
+ * class or interface that does not use preview features; consequently,
+ * this method always returns {@code false} when preview features are disabled.
+ *
+ * @return {@code true} if and only if this field is a strictly-initialized
+ * field, as defined by the Java Virtual Machine Specification
+ * @jvms strict-fields-4.5 Field access and property flags
+ * @since 28
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.STRICT_FIELDS, reflective = true)
+ public boolean isStrictInit() {
+ return accessFlags().contains(AccessFlag.STRICT_INIT);
+ }
+
/**
* Returns a {@code Class} object that identifies the
* declared type for the field represented by this
* {@code Field} object.
*
* field (or a subclass or implementor thereof).
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public boolean getBoolean(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public byte getByte(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public char getChar(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public short getShort(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public int getInt(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public long getLong(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public float getFloat(Object obj)
* widening conversion.
* @throws NullPointerException if the specified object is null
* and the field is an instance field.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
+ * @throws IllegalStateException if the current thread is initializing the
+ * field's {@linkplain #getDeclaringClass() declaring class} and
+ * the field is a {@linkplain #isStrictInit() strictly-initialized}
+ * static field that has not been initialized.
* @see Field#get
*/
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public double getDouble(Object obj)
* open} to the caller's module.</li>
* </ol>
* </li>
* <li>{@code D} is not a {@linkplain Class#isRecord() record class}.</li>
* <li>{@code D} is not a {@linkplain Class#isHidden() hidden class}.</li>
+ * <li>{@code D} is not a {@linkplain Class#isValue() value class}.</li>
* <li>The field is non-static.</li>
+ * <li>The field is not a {@linkplain #isStrictInit() strictly-initialized} field. </li>
* </ul>
*
* <p>If any of the above conditions is not met, this method throws an
* {@code IllegalAccessException}.
*
* <li>final field mutation is enabled for the unnamed module.</li>
* <li>The field is {@code public} and {@code D} is {@code public} in a package that
* is {@linkplain Module#isExported(String) exported} to all modules.</li>
* <li>{@code D} is not a {@linkplain Class#isRecord() record class}.</li>
* <li>{@code D} is not a {@linkplain Class#isHidden() hidden class}.</li>
+ * <li>{@code D} is not a {@linkplain Class#isValue() value class}.</li>
* <li>The field is non-static.</li>
+ * <li>The field is not a {@linkplain #isStrictInit() strictly-initialized} field. </li>
* </ul>
*
* <p>If any of the above conditions is not met, this method throws an
* {@code IllegalAccessException}.
*
@Override
/* package-private */ Field getRoot() {
return root;
}
+ private static final int TRUST_FINAL = 0x0010;
+ private static final int NULL_RESTRICTED = 0x0020;
+
/* package-private */ boolean isTrustedFinal() {
- return trustedFinal;
+ return (flags & TRUST_FINAL) == TRUST_FINAL;
+ }
+
+ /* package-private */ boolean isNullRestricted() {
+ return (flags & NULL_RESTRICTED) == NULL_RESTRICTED;
}
/**
* {@inheritDoc}
*
< prev index next >