Почему разрешается доступ к закрытым полям Java через отражение? - PullRequest
43 голосов
/ 06 августа 2009

Рассмотрим этот пример:

import java.lang.reflect.Field;

public class Test {

    public static void main(String[] args) {
        C c = new C();
        try {
            Field f = C.class.getDeclaredField("a");
            f.setAccessible(true);
            Integer i = (Integer)f.get(c);
            System.out.println(i);
        } catch (Exception e) {}
    }
}

class C {
    private Integer a =6;
}

Кажется нелогичным, что вам разрешен доступ к закрытым полям классов с отражением Почему такая функциональность доступна? Разве не опасно разрешать такой доступ?

Ответы [ 7 ]

58 голосов
/ 06 августа 2009

Private предназначен для предотвращения случайного неправильного использования, а не как механизм безопасности. Если вы решите обойти это, вы можете сделать это на свой страх и риск и при условии, что вы знаете, что делаете.

22 голосов
/ 06 августа 2009

Обе getDeclaredField() и setAccessible() на самом деле проверяются менеджером безопасности и выдают исключение, когда ваш код не может это сделать. Чаще всего вы этого не замечаете, потому что код Java часто запускается без менеджера безопасности.

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

10 голосов
/ 06 августа 2009

Да, это нехорошо, но позволяет работать таким фреймворкам, как Java-сериализация.

Установка флага доступности в отраженном объекте позволяет сложным приложениям с достаточными привилегиями, такими как Сериализация объектов Java или другие механизмы персистентности, манипулировать объектами способом, который обычно запрещен.

Я считаю, что функциональность может быть отключена через SecurityManager

http://javabeans.asia/2008/10/12/how_to_set_securitymanager_and_java_security_policy_programmatically.html

8 голосов
/ 06 августа 2009

Отражение опасно. Период.

Какой смысл ограничивать полезность действительно опасной системы ради чуть более повышенной безопасности?

Кроме того, автоматическая сериализация требует способности «высосать мозги» из любого класса; игнорирование модификаторов доступа является необходимостью в этом случае.

4 голосов
/ 06 августа 2009

Reflection - это полный API для доступа к классам. Частные участники и все.

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

3 голосов
/ 06 августа 2009

Из описания пакета java.lang.reflect:

Классы в этом пакете вместе с java.lang.Class размещение приложения, такие как отладчики, переводчики, инспекторы объектов, класс браузеры и сервисы, такие как Object Сериализация и JavaBeans, которые нуждаются доступ либо к публичным членам целевой объект (на основе его времени выполнения класс) или члены, объявленные данный класс.

Reflection предоставляет механизм доступа к информации о классах средствами, которые обычно недоступны при регулярном взаимодействии между классами и объектами. Одним из них является предоставление доступа к закрытым полям извне классов и объектов.

Да, отражение в целом действительно может быть опасным, поскольку оно может обнажить внутренности классов и объектов.

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

3 голосов
/ 06 августа 2009

От: http://java.sun.com/docs/books/tutorial/reflect/

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

Это инструмент, который позволяет нарушить некоторые правила, можно перебросить его через ногу или правильно его использовать.

...