在Java 12及以上版本中更改静态final字段。

huangapple go评论105阅读模式
英文:

Change static final field in java 12+

问题

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

然而,那个问题的回答在Java 12+中不起作用,因为您无法使用反射访问java.lang.reflect.Field的私有变量。

尽管如此,如果您尝试这样做,您将会得到一个类似以下的堆栈跟踪:

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

在这些版本中是否有任何更改此类常量的方法?

我可以想象可以利用JNI/JNA来实现。

英文:

This question is strongly related to Change private static final field using Java reflection. There, it was asked, how to change a private static final variable.


However, the answers on that question do not work in Java 12+ as you cannot access private variables of java.lang.reflect.Field using Reflection.

When you try to do it despite that, you will end up with a stack trace like:

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

Is there any way to change such a constant in those versions?

I could imagine being possible utilizing JNI/JNA.

答案1

得分: 15

你可以使用 Unsafe

public class Example
{
    // javac 将会内联静态 final 字符串,所以假设它是 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
英文:

You can use 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);
    }
}

Result:

before = xxx
after = it works

huangapple
  • 本文由 发表于 2020年4月10日 21:58:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/61141836.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定