3

这个问题与使用 Java 反射更改私有静态最终字段密切相关。在那里,有人问,如何改变一个private static final变量。


但是,该问题的答案在 Java 12+ 中不起作用,因为您无法访问java.lang.reflect.Field使用反射的私有变量。

尽管如此,当您尝试这样做时,您最终会得到如下堆栈跟踪:

Exception java.lang.NoSuchFieldException: modifiers
      at Class.getDeclaredField (Class.java:2412)
      at <your call of Field.class.getDeclaredField("modifiers").setAccessible(true)>

有没有办法在这些版本中改变这样的常数?

我可以想象使用 JNI/JNA 是可能的。

4

1 回答 1

10

您可以使用Unsafe.

public class Example
{
    // javac will inline static final Strings, so let's say it's Object
    private static final Object changeThis = "xxx";

    public static void main(String... args) throws Exception
    {
        final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        final Unsafe unsafe = (Unsafe) unsafeField.get(null);

        System.out.println("before = " + changeThis);

        final Field ourField = Example.class.getDeclaredField("changeThis");
        final Object staticFieldBase = unsafe.staticFieldBase(ourField);
        final long staticFieldOffset = unsafe.staticFieldOffset(ourField);
        unsafe.putObject(staticFieldBase, staticFieldOffset, "it works");

        System.out.println("after = " + changeThis);
    }
}

结果:

before = xxx
after = it works
于 2020-04-11T01:04:09.997 回答