При каких ситуациях Java в field.setAccessible (true) не будет работать? - PullRequest
7 голосов
/ 11 октября 2009

У меня есть ситуация, когда пользовательский код выбрасывает IllegalAccessException в поле, доступ к которому осуществляется с помощью отражения. Непосредственно перед доступом к полю вызывается setAccessible(true). Итак, мне кажется, что этот метод молча терпит неудачу.

В каких ситуациях это может произойти? Может ли это быть как-то связано с менеджером безопасности?

Вот фрагмент кода, который вызывает исключение:

private static Field levelField;
public int getLevel() {
    try {
        if (levelField == null) {
            levelField = MessageInfo.class.getDeclaredField("level");
            levelField.setAccessible(true);
        }
        return levelField.getInt(this);  // <-- IllegalAccessException thrown here
    } catch (Exception e) {
         handleException(e);
    }
    return ICompilationUnit.NO_AST;
}

Ответы [ 3 ]

6 голосов
/ 11 октября 2009

Это не должно быть проблемой менеджера безопасности - вы получите исключение SecurityException или подкласс.

Код levelField.getInt(*this*) выглядит не так ...

Вы должны передать экземпляр MessageInfo в качестве параметра.

Вы называете это из класса MessageInfo? (почему?!?) или подкласс MessageInfo? (Попытка заставить приватное поле суперкласса действовать так, как если бы оно было защищено? Есть ли у MessageInfo метод getLevel()? Если это так, вы можете вызвать super.getLevel(), чтобы получить значение, вместо того, чтобы пытаться его таким образом.)

Если это не MessageInfo или подкласс, это ваша проблема - у вас есть поле level класса MessageInfo, и вы пытаетесь получить значение этого поля из текущего класса. Хотя это должно быть IllegalArgumentExeception вместо IllegalAccessException ...

Если это действительно "IllegalAccessExeception" - попробуйте поместить некоторые записи в этот блок if (levelField == null) - убедитесь, что это действительно выполняется. Поле является статическим - может быть какой-то другой экземпляр или метод, устанавливающий значение для него.

4 голосов
/ 12 октября 2009

setAccessible задокументировано, чтобы бросить SecurityException. Обратите внимание, что в документации приводятся случаи, когда SecurityException будет выброшено, даже если SecurityManager отсутствует. Конечно, это также может произойти сбой из-за асинхронного исключения: Thread.stop, исключение, связанное с буфером NIO, или ошибка JVM.

Реальная проблема с этим кодом (кроме того, что он использует отражение) состоит в том, что существует поле, которое можно установить для частичной инициализации. Это вызывает состояние гонки (у вас изменчивая статика, поэтому вам нужно беспокоиться о потоках (подсказка, избегайте изменчивой статики!)). Другой поток может вызвать getInt на том же Field до вызова setAccessible. И, как кажется, первоначальный спрашивающий выяснил, что это не исключение и безопасно. Было бы намного безопаснее и понятнее настроить поле в статическом инициализаторе.

0 голосов
/ 11 октября 2009

Из собственной документации Java для setAccessible():

Возникает SecurityException, если флаг равен true, но доступность любого из элементов входного массива не может быть изменена (например, если объект элемента является объектом Constructor для класса Class). В случае такого SecurityException доступность объектов устанавливается для отметки для элементов массива вплоть до (и исключая) элемента, для которого произошло исключение; доступность элементов за (и в том числе) элементом, для которого произошло исключение, остается неизменной.

К сожалению, они ничего не упоминают о IllegalAccessException.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...