Каковы интересы синтетических методов?

проблема

Один друг предложил интересную проблему. Учитывая следующий код:

public class OuterClass {

    private String message = "Hello World";

    private class InnerClass {
        private String getMessage() {
            return message;
        }
    }

}

Из внешнего класса, как я могу распечатать message переменное содержание? Конечно, изменение доступности методов или полей не допускается.

(источник здесь, но это французский блог)


Решение

Код для решения этой проблемы следующий:

try {
    Method m = OuterClass.class.getDeclaredMethod("access$000", OuterClass.class);
    OuterClass outerClass = new OuterClass();
    System.out.println(m.invoke(outerClass, outerClass));
} catch (Exception e) {
    e.printStackTrace();
}

Обратите внимание, что access$000 имя метода не является стандартным (даже если этот формат настоятельно рекомендуется), и некоторые JVM будут называть этот метод access$0, Таким образом, лучшим решением является проверка синтетических методов:

Method method = null;
int i = 0;
while ((method == null) && (i < OuterClass.class.getDeclaredMethods().length)) {
    if (OuterClass.class.getDeclaredMethods()[i].isSynthetic()) {
        method = OuterClass.class.getDeclaredMethods()[i];
    }
    i++;
}
if (method != null) {
    try {
        System.out.println(method.invoke(null, new OuterClass()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

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

Вопрос

Каков интерес - для меня, как разработчика - синтетического метода? Какая может быть хорошая ситуация, когда использование синтетического может быть полезным?

3 ответа

Решение

Как вы продемонстрировали, модификаторы доступа Java являются просто информативными, и их можно обойти, используя отражение. Таким образом, ваши вопросы примерно эквивалентны "каков интерес обхода модификатора доступа?" Помимо злонамеренных целей, на ум приходит отладка; Вы можете, например, регистрировать внутреннее состояние некоторых библиотек извне библиотеки, не затрагивая сам код библиотеки вообще. Другой пример - сотрудничество с языками сценариев; если во время компиляции вы не знаете, какие классы и методы доступны, рефлексия может оказаться весьма полезной. Например, внутренности Jython используют огромное количество отражений вокруг.

Каков интерес для вас, как для разработчика, к синтетическому методу? Ну, во-первых, не вызывайте их (по причинам, объясненным другими ответчиками).

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

Конечно, есть некоторые большие "если"- я имею в виду, необходимые условия - чтобы такая уязвимость имела значение:

  1. На самом деле злоумышленник должен запустить код в вашей JVM. В большинстве случаев это не проблема, потому что единственный выполняемый код - ваш.
  2. Код злоумышленника должен находиться в том же пакете, что и ваш внутренний класс (поскольку синтетический метод объявлен как закрытый для пакета).
  3. Код злоумышленника должен быть загружен из того же загрузчика классов, что и ваш класс. Если вы разрешаете запускать ненадежный код в своей JVM (условие #1), то для ненадежного кода лучше использовать отдельный загрузчик классов.

Вы никогда не должны вызывать синтетические методы доступа, использующие отражение, они могут изменяться в зависимости от того, какой компилятор вы используете. Например, запустить ваше решение на jdk1.6 на моем компьютере не удалось, так как access$000 метод не найден.

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

Другие вопросы по тегам