※ 引述《darkk6 (Mr. Pan)》之铭言:
: → sbrhsieh:不懂darkk6 的意思 06/03 11:50
: → sbrhsieh:若我没误解,那你有能力变更 final field 的值。 06/03 11:59
: → sbrhsieh: 要 06/03 12:00
: 在不考虑 Security 的问题下,确实有方法 access final field.
: IntegerCache 的 low , high , cache 都是 static final
: 要改变还是可以做点 tricky 的方式去修改,刚刚写了一个范例如下
: http://ideone.com/XO1zGU
: 原本 IntegerCache 的范围是 -128~127 , 因此 129 不在范围内
: 这个例子中,我把 cache 范围扩增到 -128~1000 , 接着把
: 129 的 cache 值改为 5 (其实可以在第一个 trick 就处理,但我分开写)
: PS : 其实重点就是把 Field 的 final 拿掉啦~
我虽然知道 JVM(至少 sun/Oracle implementation 是)没有做 final field
access 方面的 enforcement,但是我之前有自己试验过类似你的做法却失败了。
你的 sample code 我在 Oracle JVM 试过确实可行,同时我也发现了我自己的
试验为什么会失败了(严格来说我还是不知道为什么 :D),主要是我习惯在 REPL
的模式下试验,我先试未修改 Field object 的 modifier 的情况下去变更
final field 的值,如预料是行不通的。接着在接续上一个试验的状态下,试着去
修改同一 Field object 的 modifier,即使把 final bit 移除,依然无法透过
该 Field object 来变更 final field 的值。
或许你也能在你使用的 JRE 重制出我形容的现象,试着把你的 sample code
里的 setFinalStaticValue method 稍作修改:
private static void setFinalStaticValue(Field fd,Object val){
try{
fd.setAccessible(true);
Field mdfField = Field.class.getDeclaredField("modifiers");
mdfField.setAccessible(true);
try {
fd.set(null, val);
}
catch (Exception e) {}
//重点是这里,把 final 属性拿掉
mdfField.setInt(fd, fd.getModifiers() & ~Modifier.FINAL);
fd.set(null, val);
} catch(Exception e){
e.printStackTrace();
}
}
编译后试试看你使用的 JRE 来执行还行不行得通?
那我讲这些东西的重点是?没有,我只是陈述整个事件始末,陈述一个事实,这个
行为是不是违规的知识分享,法院自会有判断。