Пакет java.lang.module
Классы для поддержки описателей модулей и создания конфигураций модулей с помощью разрешения и привязки сервисов.
Если не указано иное, передача аргумента null конструктору или методу любого класса или интерфейса в этом пакете приведет к тому, что будет брошено исключение NullPointerException. Кроме того, вызов метода с массивом или коллекцией, содержащей элемент null, вызовет исключение NullPointerException, если не указано иное.
Разрешение модулей
Разрешение — это процесс вычисления того, как модули зависят друг от друга. Процесс происходит во время компиляции и выполнения.
Разрешение — это двухэтапный процесс. На первом этапе рекурсивно перечисляются директивы 'requires' набора корневых модулей. Если все перечисленные модули наблюдаемы, то на втором этапе вычисляется граф их читаемости. Граф читаемости отражает, как модули зависят друг от друга, что, в свою очередь, управляет доступом через границы модулей.
Шаг 1: Рекурсивное перечисление
Рекурсивное перечисление принимает набор имён модулей, ищет объявления каждого из них и для каждого объявления модуля рекурсивно перечисляет:
-
имена модулей, заданные директивами 'requires' с модификатором 'transitive', и
-
по усмотрению хостовой системы, имена модулей, заданные директивами 'requires' без модификатора 'transitive'.
Объявления модулей ищутся в наборе наблюдаемых модулей. Набор наблюдаемых модулей определяется с учётом конкретной реализации. Набор наблюдаемых модулей может включать модули с явными объявлениями (то есть с файлом исходного кода module-info.java или файлом module-info.class) и модули с неявными объявлениями (то есть автоматические модули). Поскольку у автоматического модуля нет явного объявления модуля, у него нет собственных директив 'requires', хотя его имя может быть задано директивой 'requires' явного объявления модуля.
Набор корневых модулей, имена которых являются начальным входом в этот алгоритм, определяется с учётом конкретной реализации. Набор корневых модулей может включать автоматические модули.
Если по крайней мере один автоматический модуль перечисляется этим алгоритмом, то каждый наблюдаемый автоматический модуль должен быть перечислен, независимо от того, указаны ли какие-либо из их имён директивами 'requires' явных объявлений модулей.
Если произойдёт хотя бы одно из следующих условий, то разрешение завершается неудачей:
Корневой модуль не наблюдаем.
Любой модуль, имя которого задано директивой 'requires' с модификатором 'transitive', не наблюдаем.
По усмотрению хостовой системы, любой модуль, имя которого задано директивой 'requires' без модификатора 'transitive', не наблюдаем.
В алгоритме в этом шаге дважды перечисляется одно и то же имя модуля. Это указывает на цикл в директивах 'requires', не учитывая модификаторы 'transitive'.
В противном случае разрешение переходит к шагу 2.
Шаг 2: Вычисление графа читаемости
Директива 'requires' (независимо от 'transitive') выражает, что один модуль зависит от другого модуля. Действие модификатора 'transitive' заключается в том, чтобы заставить дополнительные модули также зависеть от другого модуля. Если модуль M 'requires transitive N', то M зависит не только от N, но и любой модуль, который зависит от M, также зависит от N. Это позволяет переиспользовать M таким образом, чтобы часть или весь его контент мог быть перемещён в новый модуль N без нарушения модулей, имеющих директиву 'requires M'.
Зависимости модулей представлены графом читаемости. Граф читаемости — это ориентированный граф, вершинами которого являются перечисленные на шаге 1 модули, а рёбра представляют читаемость между парами модулей. Рёбра задаются следующим образом:
Во-первых, читаемость определяется директивами 'requires' перечисленных модулей, не учитывая модификаторы 'transitive':
Для каждого перечисленного модуля A, который 'requires' B: A «читает» B.
Для каждого перечисленного автоматического модуля X: X «читает» каждый другой перечисленный модуль (будто у автоматического модуля есть директивы 'requires' для каждого другого перечисленного модуля).
Во-вторых, читаемость дополняется с учётом модификатора 'transitive':
-
Для каждого перечисленного модуля A, который «читает» B:
Если B 'requires transitive' C, то A «читает» C так же, как и B. Это дополнение рекурсивно: так как A «читает» C, то, если C 'requires transitive' D, то A «читает» D так же, как и C и B.
-
Если B — автоматический модуль, то A «читает» каждый другой перечисленный автоматический модуль. (Будто у автоматического модуля есть директивы 'requires transitive' для каждого другого перечисленного автоматического модуля).
Наконец, каждый модуль «читает» сам себя.
Если в графе читаемости произойдёт любое из следующих условий, то разрешение завершается неудачей:
Модуль «читает» два или более модуля с одинаковым именем. Это включает случай, когда модуль «читает» другой с тем же именем, что и у него самого.
Два или более модуля экспортируют пакет с одинаковым именем в модуль, который «читает» оба. Это включает случай, когда модуль M, содержащий пакет p, «читает» другой модуль, который экспортирует p в M.
Модуль M объявляет, что он 'uses p.S' или 'provides p.S with...', но пакет p не находится ни в модуле M, ни экспортирован в M каким-либо модулем, который M «читает».
В противном случае разрешение завершается успешно, и результатом разрешения является граф читаемости.
Корневые модули
Набор корневых модулей во время компиляции обычно состоит из модулей, которые компилируются. Во время выполнения набор корневых модулей обычно является модулем приложения, указанным в запускающей команде 'java'. При компиляции кода в безымянном модуле или во время выполнения, когда главный класс приложения загружается из пути к классам, набор корневых модулей по умолчанию определяется с учётом конкретной реализации. В JDK набор корневых модулей по умолчанию содержит каждый модуль, который наблюдаем в пути апгрейда модулей или среди системных модулей и который экспортирует хотя бы один пакет без квалификатора.
Наблюдаемые модули
Набор наблюдаемых модулей как во время компиляции, так и во время выполнения определяется путём поиска по нескольким различным путям, а также путём поиска скомпилированных модулей, встроенных в среду.
Порядок поиска следующий:Только во время компиляции, путь компиляции модуля. Этот путь содержит определения модулей в исходной форме.
Путь апгрейда модуля. Этот путь содержит скомпилированные определения модулей, которые будут наблюдаться в приоритете по сравнению со скомпилированными определениями любых обновляемых модулей, присутствующих в (3) и (4). См. Java SE Platform для определения того, какие стандартные модули являются обновляемыми.
Системные модули, которые являются скомпилированными определениями, встроенными в среду.
Путь модуля приложения. Этот путь содержит скомпилированные определения библиотечных и прикладных модулей.
Директивы 'requires' с модификатором 'static'
Директивы 'requires', имеющие модификатор 'static', выражают необязательную зависимость во время выполнения. Если модуль объявляет, что он 'requires static M', то разрешение не ищет наблюдаемые модули для удовлетворения зависимости M. Однако, если M рекурсивно перечисляется на шаге 1, то все модули, которые перечисляются и `requires static M`, будут читать M.
Полнота
Разрешение может быть частичным во время компиляции в том смысле, что полное транзитивное замыкание может не потребоваться для компиляции набора модулей. Минимально, граф читаемости, который строится и проверяется во время компиляции, включает модули, которые компилируются, их прямые зависимости и все неявные объявленные зависимости (requires transitive).
Во время выполнения разрешение — это аддитивный процесс. Рекурсивное перечисление на шаге 1 может относиться к предыдущим разрешениям, так что корневой модуль или модуль, имя которого указано в директиве 'requires', не перечисляется, когда он был перечислен предыдущим (или родительским) разрешением. Граф читаемости, который является результатом разрешения, может, следовательно, иметь вершину для модуля, перечисленного на шаге 1, но с ребром, которое представляет, что модуль читает модуль, перечисленный предыдущим (или родительским) разрешением.
- С:
- 9
| Интерфейс | Описание |
|---|---|
| ModuleFinder | Поисковик модулей. |
| ModuleReader | Обеспечивает доступ к содержимому модуля. |
| Класс | Описание |
|---|---|
| Configuration | Конфигурация, являющаяся результатом разрешения или разрешения с привязкой сервисов. |
| ModuleDescriptor | Описатель модуля. |
| ModuleDescriptor.Builder | Построитель для создания объектов |
| ModuleDescriptor.Exports | Экспортируемый модулем пакет, может быть квалифицированным или неквалифицированным. |
| ModuleDescriptor.Opens | Открытый модулем пакет, может быть квалифицированным или неквалифицированным. |
| ModuleDescriptor.Provides | Сервис, который модуль предоставляет с одним или несколькими реализациями. |
| ModuleDescriptor.Requires | Зависимость от модуля |
| ModuleDescriptor.Version | Строка версии модуля. |
| ModuleReference | Ссылка на содержимое модуля. |
| ResolvedModule | Модуль в графе разрешенных модулей. |
| Перечисление | Описание |
|---|---|
| ModuleDescriptor.Exports.Modifier | Модификатор экспортируемого пакета. |
| ModuleDescriptor.Modifier | Модификатор модуля. |
| ModuleDescriptor.Opens.Modifier | Модификатор открытого пакета. |
| ModuleDescriptor.Requires.Modifier | Модификатор зависимости от модуля. |
| Исключение | Описание |
|---|---|
| FindException | Выбрасывается |
| InvalidModuleDescriptorException | Выбрасывается при чтении описания модуля, если описание модуля имеет неправильный формат или иным образом не может быть интерпретировано как описание модуля. |
| ResolutionException | Выбрасывается, когда происходит сбой при разрешении набора модулей или набора модулей со связыванием служб. |
© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/package-summary.html