Java Reflection, изменение приватного статического поля final ничего не делало - PullRequest
5 голосов
/ 22 февраля 2012

Я пытаюсь изменить частное статическое конечное поле с помощью Java Reflection.Но это просто провал.У кого-то была идея?

Вот мой код:

public class SecuredClass {
    private static final String securedField = "SecretData";
    public static String getSecretData() { return securedField; }
}

public class ChangeField {
    static void setFinalStatic(Field field, Object newValue) throws Exception
    {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);

        field.set(null, newValue);
    }

    public static void main(String args[]) throws Exception
    {
        System.out.println("Before = " + SecuredClass.getSecretData());

        Field stringField = SecuredClass.class.getDeclaredField("securedField");
        stringField.setAccessible(true);
        setFinalStatic(stringField, "Screwed Data!");


        System.out.println("After = " + Java_FileMerger_Main.getSecretData());
    }
}

А вот мой вывод:

Before = SecretData
After = SecretData

I 'мы пытались удалить SecurityManager с помощью System.setSecurityManager (null);Но это ничего не изменило.Я знаю, что это зло, но я хочу, чтобы это сработало.Я надеюсь, что кто-то может мне помочь.

Ответы [ 3 ]

6 голосов
/ 22 февраля 2012

Семантика изменения конечных полей с помощью отражения не определена (см. спецификация ). Не гарантируется, что отражающая запись в конечное поле когда-либо будет видна при чтении из поля.

Особенно для статических полей final, которым назначена константа (как в вашем случае), компилятор будет часто вставлять константу, и, таким образом, поле не будет доступно вообще во время выполнения (только при использовании отражения).

SecurityManager здесь не актуален. Если использование рефлексии было бы запрещено SecurityManager, операция вызвала бы исключение и не потерпела бы неудачу молча.

Ответы на вопрос Изменение частного статического конечного поля с использованием отражения Java предоставляют более подробные сведения, включая пример, в котором вы можете увидеть в байтовом коде, что константы становятся встроенными.

1 голос
/ 31 декабря 2013

Для этого есть обходной путь. если вы установите значение приватного статического финала, поданного в статическом блоке {}, оно будет работать, потому что оно не будет встроено в поле:

private static final String MY_FIELD;

static {
    MY_FIELD = "SomeText"
}

...

Field field = VisitorId.class.getDeclaredField("MY_FIELD");

field.setAccessible(true);
field.set(field, "fakeText");
1 голос
/ 12 сентября 2013

У меня также были проблемы с приведенным выше примером. Для меня это сработало после того, как я определил строку не как литерал, а как объект.

private static final String SECURED_FIELD = String.valueOf("SecretData");

Или

private static final String SECURED_FIELD = new String("SecretData");

Не лучшее решение, если вы хотите извлечь выгоду из литералов, но мне не нужно было заботиться об этом.

...