![](/img/trans.png)
[英]Set private field with reflection works on static OR final, but not static final (combined)
[英]Java reflection to set static final field fails after previous reflection
在Java中,事實證明,字段訪問器被緩存,並且使用訪問器具有副作用。 例如:
class A {
private static final int FOO = 5;
}
Field f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
f.getInt(null); // succeeds
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // fails
而
class A {
private static final int FOO = 5;
}
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // succeeds
這是失敗的堆棧跟蹤的相關位:
java.lang.IllegalAccessException: Can not set static final int field A.FOO to (int)6
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:100)
at sun.reflect.UnsafeQualifiedStaticIntegerFieldAccessorImpl.setInt(UnsafeQualifiedStaticIntegerFieldAccessorImpl.java:129)
at java.lang.reflect.Field.setInt(Field.java:949)
這兩個反射訪問當然發生在我的代碼庫的非常不同的部分,我真的不想改變第一個來修復第二個。 有沒有辦法改變第二次反射訪問以確保它在兩種情況下都成功?
我試着看看Field
對象,它沒有任何看似他們會幫助的方法。 在調試器中,我注意到在第一個示例中返回的第二個Field
上設置了overrideFieldAccessor
,但沒有看到修改器的更改。 不過,我不知道該怎么辦。
如果它openjdk-8
,我正在使用openjdk-8
。
如果你想修飾符黑客(不要忘記它是完全黑客 ),你需要在第一次訪問該字段之前更改modifiers
私有字段。
所以,在你做f.getInt(null);
,你需要這樣做:
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
原因是,無論您有多少不同的實際java.lang.reflect.Field
對象,都只為類(*)的每個字段創建一個內部FieldAccessor
對象。 而對於檢查final
,當它構建在該FieldAccessor執行修改器進行一次UnsafeFieldAccessorFactory
。
當確定你無法訪問final static
字段時(因為setAccessible
覆蓋不起作用,但非靜態的最終字段,但不適用於static
最終字段),它將為每次后續反射保持失敗,即使是通過不同的Field
對象,因為它一直使用相同的FieldAccessor
。
(*)禁止同步問題; 作為評論中Field
提及的源代碼:
//注意這里沒有使用同步。 為給定的字段生成多個FieldAccessor是正確的(盡管效率不高)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.