Измените stati c последнее поле на java 12+ - PullRequest
0 голосов
/ 10 апреля 2020

Этот вопрос тесно связан с Изменить личное состояние c окончательное поле, используя Java отражение . Там спросили, как изменить переменную private static final.


Однако ответы на этот вопрос не работают в Java 12+, поскольку вы не можете получить доступ к закрытым переменным java.lang.reflect.Field используя Reflection.

Когда вы попытаетесь это сделать, несмотря на это, вы получите трассировку стека, например:

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

Есть ли способ изменить такую ​​константу в этих версиях?

Я мог бы представить себе возможность использования JNI / JNA.

1 Ответ

0 голосов
/ 11 апреля 2020

Вы можете использовать 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
...