我尝试应用
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";
}