尝试修改私有静态字段时出现 IllegalAccessException
IllegalAccessException when trying to modify private static field
我试着按照这个Change private static final field using Java reflection
但出于某种原因我得到 java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Integer
for (Field field : Table.getDeclaredFields()){
System.out.println(Table.getSimpleName()); //prints "Item"
field.setAccessible(true);
if (field.getName().equals(GeneratedValueFields.get(i).getName())) {
System.out.println(field.getName()); //prints "id"
Field modifiersField = Table.getDeclaredField(GeneratedValueFields.get(i).getName());
System.out.println(modifiersField.getName()); //prints "id" as expected
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); //error here
//data = 9 (Long)
field.set(null,data);
};
现在如果我删除行 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
我得到java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Long
如果我将字段更改为 private final 并指定对象
field.set(TableModel,data);
正常工作
Change private static final field using Java reflection 中的代码在 Java 1.8 中有效,但在 Java 17 中无效。
在 Java 17 中,jdk.internal.reflect.Reflection
class 包含 classes 的映射,其中的部分或全部成员应该对反射不可见:
/** Used to filter out fields and methods from certain classes from public
view, where they are sensitive or they may contain VM-internal objects.
These Maps are updated very rarely. Rather than synchronize on
each access, we use copy-on-write */
private static volatile Map<Class<?>, Set<String>> fieldFilterMap;
...
private static final String WILDCARD = "*";
public static final Set<String> ALL_MEMBERS = Set.of(WILDCARD);
static {
fieldFilterMap = Map.of(
Reflection.class, ALL_MEMBERS,
...
);
...
}
因此该示例不适用于较新的 JDK。
从 Java 12 开始就是这种情况:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8210496
我试着按照这个Change private static final field using Java reflection
但出于某种原因我得到 java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Integer
for (Field field : Table.getDeclaredFields()){
System.out.println(Table.getSimpleName()); //prints "Item"
field.setAccessible(true);
if (field.getName().equals(GeneratedValueFields.get(i).getName())) {
System.out.println(field.getName()); //prints "id"
Field modifiersField = Table.getDeclaredField(GeneratedValueFields.get(i).getName());
System.out.println(modifiersField.getName()); //prints "id" as expected
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); //error here
//data = 9 (Long)
field.set(null,data);
};
现在如果我删除行 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
我得到java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Long
如果我将字段更改为 private final 并指定对象
field.set(TableModel,data);
正常工作
Change private static final field using Java reflection 中的代码在 Java 1.8 中有效,但在 Java 17 中无效。
在 Java 17 中,jdk.internal.reflect.Reflection
class 包含 classes 的映射,其中的部分或全部成员应该对反射不可见:
/** Used to filter out fields and methods from certain classes from public
view, where they are sensitive or they may contain VM-internal objects.
These Maps are updated very rarely. Rather than synchronize on
each access, we use copy-on-write */
private static volatile Map<Class<?>, Set<String>> fieldFilterMap;
...
private static final String WILDCARD = "*";
public static final Set<String> ALL_MEMBERS = Set.of(WILDCARD);
static {
fieldFilterMap = Map.of(
Reflection.class, ALL_MEMBERS,
...
);
...
}
因此该示例不适用于较新的 JDK。
从 Java 12 开始就是这种情况:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8210496