Uncategorized

Внутренние элементы JDK, надежно инкапсулированные в JDK 17

JEP 403 (Strongly Encapsulate JDK Internals), один из 14 JEP, определенных как последний набор функций для JDK 17, строго инкапсулирует все внутренние элементы JDK, за исключением важных внутренних API, таких как sun.misc.Unsafe. Поскольку он является преемником JEP 396 (по умолчанию строго инкапсулирует внутренние компоненты JDK), он больше не сможет получить доступ к внутренним API через --illegal-access параметр командной строки.

Основная цель инкапсуляции – побудить разработчиков использовать стандартные API-интерфейсы вместо внутренних API-интерфейсов для повышения безопасности и удобства обслуживания. Это также позволяет разработчикам, которые вносят свой вклад в OpenJDK, обновлять внутренний код, не нарушая существующий код. Разработчики могут воспользоваться инструментом JDeps с плагинами Maven и Gradle, чтобы проверить, использует ли существующая кодовая база внутренние компоненты JDK.

В --add-opens Параметр командной строки, также известный как атрибут манифеста JAR-файла Add-Opens, может использоваться для открытия определенных пакетов. Рассмотрим следующий пример, который разрешит доступ всем безымянным модулям к java.util модуль.

$ java --add-opens java.base/java.util=ALL-UNNAMED 
  --classpath {classpath} -jar {jarfile}

Внутренние элементы, такие как криптографические ключи, в настоящее время доступны через отражение. Сюда входят все классы, методы и поля в sun.* пакеты. В com.sun.*, jdk.* а также org.* пакеты также содержат некоторые внутренние элементы, и список всех затронутых пакетов (внутренних и экспортированных) доступен для просмотра. Отражение все еще можно использовать через sun.misc а также sun.reflect пакеты, которые все еще экспортируются jdk.unsupported модуль.

Сильная инкапсуляция внутренних API-интерфейсов JDK постепенно развивалась за последние несколько лет с тех пор, как JDK 9 представил модульную систему, обеспечивающую надежную инкапсуляцию. Другие модули могут использовать только общедоступные и защищенные (через подклассы) классы, методы и атрибуты во время компиляции и выполнения из пакетов, экспортированных модулем.

С момента выпуска в 2017 году поддерживаемые API-интерфейсы в JDK 9 были представлены в качестве замены внутренних элементов, таких как java.util.Base64, класс, состоящий из статических методов получения кодеров и декодеров для схемы кодирования Base64. Поэтому вызовы внутренних API следует заменить вызовами поддерживаемых API.

Новые внутренние элементы, добавленные в JDK 9 и более поздних версиях, по умолчанию строго инкапсулированы. Однако внутренние API, представленные до JDK 9, не сильно инкапсулируются во время выполнения.

В JDK 9 по-прежнему можно получить доступ к внутренним API-интерфейсам с помощью упрощенной строгой инкапсуляции с помощью --illegal-access опция командной строки, впервые представленная в JEP 261. Новое значение по умолчанию --illegal-access=permit открывает весь внутренний код для безымянных модулей, в которых код может обращаться к внутренним API через отражение. Альтернатива --illegal-access=permit является --illegal-access=warn который может использоваться для выдачи предупреждения для каждого отражающего доступа. Дополнительная информация доступна через --illegal-access=debug который напечатает трассировку стека вместе с предупреждением. С участием --illegal-access=deny, любой доступ к отражению блокируется, кроме случаев, когда модуль явно открывается с другим параметром командной строки, например --add-opens.

Поставляемый в JDK 16, JEP 396 изменил параметр по умолчанию для --illegal-access из permit к deny и по-прежнему можно явно использовать другие параметры. JEP 396 уже не рекомендует --illegal-access параметр командной строки, при использовании которого выдается предупреждение об устаревании.

С выпуском JDK 17 доступ будет в дальнейшем ограничен внутренними API. В --illegal-access опция больше не разрешает доступ к внутренним API. Вместо этого --add-opens Параметр командной строки может использоваться для открытия определенных пакетов.

Попытка использовать --illegal-access параметр командной строки с JDK 17, например, со значением permit, в командной строке появится предупреждение:

$ java --illegal-access=permit {filename}.java

OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=permit; 
  support was removed in 17.0

Ожидается, что в будущем эта опция будет полностью удалена.

Попытка получить доступ к внутреннему API в исходном коде приведет к следующему исключению:

java.lang.reflect.InaccessibleObjectException: 
  Unable to make field private final {type} accessible:
  module java.base does not "opens {module}" to unnamed module {module}

Некоторые ответы сообщества Java включали: Николай Парлог, защитник разработчиков в Oracle, представил задний план об использовании внутренних API JDK; и OkHttp, HTTP-проект, предлагаемый Square Open Source, задокументировали, как JEP 403 повлиял на их проект с помощью внутренних API.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button