You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用Unsafe修改其他类static final字段前需触发类初始化?

关于sun.misc.Unsafe修改public static final字段的问题

我尝试使用sun.misc.Unsafe修改类的public static final字段,用于单元测试和JMH基准测试。在JDK11至JDK17版本测试发现,只有在创建该类对象或调用其静态方法作为触发操作后,修改才能正常生效。

核心问题

  1. 为何修改前必须执行该触发操作?
  2. 是否存在执行步骤更少、内存消耗更低的修改方式?

更多细节

部分触发方式仅在特定平台或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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 23:47:07