Каковы интересы синтетических методов? - PullRequest
2 голосов
/ 17 марта 2010

Задача

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

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 ]

1 голос
/ 17 марта 2010

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

1 голос
/ 17 марта 2010

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

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

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

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

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

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

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