что такое нелегальный рефлексивный доступ - PullRequest
0 голосов
/ 09 мая 2018

Существует множество вопросов о нелегальном отражающем доступе в Java 9.

Теперь я не могу найти, потому что все, что Google выдает, это люди, пытающиеся обойти сообщения об ошибках, это то, что нелегальноеРефлексивный доступ на самом деле.

Итак, мой вопрос довольно прост:

Что определяет нелегальный рефлексивный доступ и какие обстоятельства вызывают предупреждение?

Я понял, что у него что-то естьделать с принципами инкапсуляции, которые были введены в Java 9, но как все это сваливается вместе и что вызывает предупреждение, в каком сценарии я не могу найти объяснение.

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Просто посмотрите на setAccessible() метод, используемый для доступа к private полям и методам:

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-

https://docs.oracle.com/javase/9/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-

Теперь для работы этого метода требуется намного больше условий. Единственная причина, по которой он не ломает почти все старое программное обеспечение, заключается в том, что модули, автоматически сгенерированные из простых JAR-файлов, очень разрешительны (открывают и экспортируют все для всех).

0 голосов
/ 09 мая 2018

Помимо понимания доступа между модулями и их соответствующими пакетами. Я полагаю, что суть этого заключается в модульной системе # Relaxed-strong-encapsulation , и я бы просто выбрал соответствующие части, чтобы попытаться ответить на вопрос.

Что определяет нелегальный рефлексивный доступ и какие обстоятельства вызвать предупреждение?

Для облегчения перехода на Java9 сильная инкапсуляция модулей может быть ослаблена.

  • Реализация может обеспечивать статический доступ , т. Е. Скомпилированным байт-кодом.

  • Может предоставить средство для вызова своей системы времени выполнения с одним или несколькими пакетами одного или нескольких из его модулей, открытых для кода в всех неназванных модулей , то есть для кодирования на пути к классам. Если во время выполнения система вызывается таким образом, и если при этом некоторые вызовы API-интерфейсов отражения выполняются успешно, то в противном случае они бы потерпели неудачу.

В таких случаях вы фактически сделали отражающий доступ , который "незаконен" , так как в чисто модульном мире вам не предназначались такие доступы.

Как все это сочетается и что вызывает предупреждение в чем сценарий

Это ослабление инкапсуляции контролируется во время выполнения новой опцией запуска --illegal-access, которая по умолчанию в Java9 равна permit. Режим permit обеспечивает

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

Режимы конфигурируются со значениями debug (сообщение, а также трассировка стека для каждого такого доступа), warn (сообщение для каждого такого доступа) и deny (отключает такие операции).


Мало что можно отладить и исправить в приложениях: -

  • Запустите его с помощью --illegal-access=deny, чтобы узнать и избегать открытия пакетов из одного модуля в другой без объявления модуля, включающего такую ​​директиву (opens) или явное использование --add-opens VM arg.
  • Статические ссылки из скомпилированного кода на внутренние API JDK могут быть идентифицированы с помощью инструмента jdeps с опцией --jdk-internals

    Предупреждение о недопустимой операции отраженного доступа обнаружен имеет следующую форму:

    WARNING: Illegal reflective access by $PERPETRATOR to $VICTIM
    

    где:

    $PERPETRATOR - полное имя типа, содержащего код, который вызвал отражательную операцию, а также код источник (то есть путь к JAR-файлу), если он доступен, и

    $VICTIM - строка, которая описывает доступ к члену, включая полное имя типа вложения

Вопросы для такого примера предупреждения: = JDK9: Произошла недопустимая операция доступа с отражением. org.python.core.PySystemState

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

0 голосов
/ 09 мая 2018

Существует статья Oracle , которую я нашел относительно модульной системы Java 9

По умолчанию тип модуля недоступен другим модулям, если он не является общедоступным типом и вы не экспортируете его пакет. Вы выставляете только те пакеты, которые хотите выставить. В Java 9 это также относится к рефлексии.

Как указано в https://stackoverflow.com/a/50251958/134894,, различия между AccessibleObject#setAccessible для JDK8 и JDK9 поучительны. В частности, JDK9 добавил

Этот метод может использоваться вызывающей стороной в классе C, чтобы разрешить доступ к члену объявления класса D, если выполнено любое из следующих действий:

  • C и D находятся в одном модуле.
  • Элемент public, а D public в пакете, который модуль, содержащий D, экспортирует, по крайней мере, в модуль, содержащий C.
  • Элемент защищен статически, D является общедоступным в пакете, который модуль, содержащий D, экспортирует как минимум в модуль, содержащий C, а C является подклассом D.
  • D находится в пакете, который модуль, содержащий D, открывает по крайней мере для модуля, содержащего C. Все пакеты в неназванных и открытых модулях открыты для всех модулей, и поэтому этот метод всегда завершается успешно, когда D находится в неназванном или открытом модуле.

, который подчеркивает важность модулей и их экспорта (в Java 9)

...