[英]Java Reflection, change private static final field didn't do anything
我正在嘗試使用Java Reflection更改私有靜態final字段。 但它只是失敗了。 有人有想法嗎?
這是我的代碼:
public class SecuredClass {
private static final String securedField = "SecretData";
public static String getSecretData() { return securedField; }
}
public class ChangeField {
static void setFinalStatic(Field field, Object newValue) throws Exception
{
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception
{
System.out.println("Before = " + SecuredClass.getSecretData());
Field stringField = SecuredClass.class.getDeclaredField("securedField");
stringField.setAccessible(true);
setFinalStatic(stringField, "Screwed Data!");
System.out.println("After = " + Java_FileMerger_Main.getSecretData());
}
}
這是我的輸出:
Before = SecretData
After = SecretData
我試圖用System.setSecurityManager(null)刪除SecurityManager; 但它沒有改變任何東西。 我知道這是邪惡的,但我想讓它發揮作用。 我希望有人可以幫助我。
通過反射改變最終字段的語義沒有定義(參見規范 )。 不能保證在從場上讀取時會看到對最終場的反射寫入。
特別是對於具有常量分配的靜態final字段(如在您的情況下),編譯器通常會內聯常量,因此在運行期間根本不會訪問該字段(僅當您使用反射時)。
SecurityManager與此處無關。 如果SecurityManager禁止使用反射,則操作將拋出異常,並且不會以靜默方式失敗。
問題的答案使用Java反射更改私有靜態最終字段提供了一些更多細節,包括一個示例,您可以在字節代碼中看到常量被內聯。
我也遇到了上面給出的例子的問題。 對我來說,在我沒有將String定義為文字而是將其定義為Object之后,它才起作用。
private static final String SECURED_FIELD = String.valueOf("SecretData");
要么
private static final String SECURED_FIELD = new String("SecretData");
如果你想從文字中受益,這不是最好的解決方案,但我不必關心它。
有一個解決方案。 如果你在static {}塊中設置private static final字段的值,它將起作用,因為它不會內聯字段:
private static final String MY_FIELD;
static {
MY_FIELD = "SomeText"
}
...
Field field = VisitorId.class.getDeclaredField("MY_FIELD");
field.setAccessible(true);
field.set(field, "fakeText");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.