为何用Unsafe修改其他类static final字段前需触发类初始化?
关于sun.misc.Unsafe修改public static final字段的问题
我尝试使用sun.misc.Unsafe修改类的public static final字段,用于单元测试和JMH基准测试。在JDK11至JDK17版本测试发现,只有在创建该类对象或调用其静态方法作为触发操作后,修改才能正常生效。
核心问题
- 为何修改前必须执行该触发操作?
- 是否存在执行步骤更少、内存消耗更低的修改方式?
更多细节
部分触发方式仅在特定平台或JDK版本生效:
以下两种写法在Sololearn平台的JDK 16-ea版本中可行,但在我的OpenJDK 15.0.2+7(macOS 13.1上的Zulu15.29.15)中无效:
Object o = Another.class; // ...或
{ Object o = Another.class; } // save stack // ...而以下两种触发方式在两个平台均可行:
{ Object a = new Another(); } // ...或
Another.hi(); // ... class Another { public static void hi () {} }
完整示例代码
import sun.misc.Unsafe; import java.lang.reflect.Field; public class Program { public static final Object SF = "Original"; public static void main(String[] args) throws Exception { //////////////////////////////////////////////////////////////////////////////// // Test with this class modify(Program.class.getDeclaredField("SF"), "New-1"); System.out.println("Program.SF:\t" + Program.SF); // Worked: Program.SF: New-1 modify(Program.class.getDeclaredField("SF"), "New-2"); System.out.println("Program.SF:\t" + Program.SF); // Worked: Program.SF: New-2 //////////////////////////////////////////////////////////////////////////////// // Test with another class modify(Another.class.getDeclaredField("SF"), "New-1"); System.out.println("Another.SF:\t" + Another.SF); // Failed: Another.SF: Original // like a trigger { Object c = new Another(); } modify(Another.class.getDeclaredField("SF"), "New-2"); System.out.println("Another.SF:\t" + Another.SF); // Worked: Another.SF: New-2 } public static void modify(Field f, Object v) throws Exception { Field fu = Unsafe.class.getDeclaredField("theUnsafe"); fu.setAccessible(true); Unsafe u = (Unsafe) fu.get(null); u.putObject( u.staticFieldBase(f), u.staticFieldOffset(f), v ); } } class Another { public static final Object SF = "Original"; }
内容的提问来源于stack exchange,提问作者BingLi224
相关产品推荐
相关产品推荐

