为什么必须在使用 Unsafe 修改另一个类的静态最终字段之前创建或调用 Java 类?

问题描述 投票:0回答:0

我尝试应用

sun.misc.Unsafe
修改某些类的
public static final
字段以进行单元测试和
jmh
基准测试。至少用 JDK11 到 JDK17 进行测试,它似乎只有在创建类对象或该类的某些静态函数作为触发器调用后才能正常工作。我的完整代码在底部。

问题

  • 为什么要求修改前?
  • 有没有其他的修改方式,执行次数少,内存消耗少?

更多详情

有些方法只适用于SOME平台或JDK版本。例如:

Object o = Another.class;

// ...

{
    Object o = Another.class;
} // save stack

// ...

在 sololearn 操场上使用版本“16-ea”,但不适用于我的 OpenJDK 15.0.2+7(macOS 13.1 上的 Zulu15.29.15)。

另一种适用于两个平台的方法:

{
    Object a = new Another();
}

// ...

Another.hi();

// ...

class Another () {
    public static void hi () {}
}

参考

https://stackoverflow.com/a/61150853/8244977

完整示例

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";
}
java reflection static final unsafe
© www.soinside.com 2019 - 2024. All rights reserved.