JEP 200: The Modular JDK
Модульный JDK
| Ответственный | Mark Reinhold |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 9 |
| JSR | 376 |
| Обсуждение | jigsaw dash dev at openjdk dot java dot net |
| Трудоёмкость | XL |
| Длительность | XL |
| Зависит от | JEP 201: Modular Source Code |
| JEP 220: Modular Run-Time Images | |
| JEP 261: Module System | |
| Рецензенты | Alan Bateman, Alex Buckley, Paul Sandoz |
| Одобрен | Brian Goetz |
| Создан | 2014/07/22 14:08 |
| Обновлён | 2017/09/21 14:30 |
| Задача | 8051618 |
Аннотация
Использовать Java Platform Module System, описанную в JSR 376 и реализованную в JEP 261, для разбиения JDK на модули.
Цели
Разделить JDK на набор модулей, которые можно объединять на этапе компиляции, сборки и выполнения в различные конфигурации, в том числе (но не только):
-
конфигурации, соответствующие полной платформе Java SE, полному JRE и полному JDK;
-
конфигурации, примерно равные по содержимому каждому из профилей Compact Profiles, определённых в Java SE 8; и
-
пользовательские конфигурации, которые содержат только заданный набор модулей, возможно дополненный модулями внешних библиотек и приложений, а также модули, транзитивно требуемые всеми этими модулями.
Определение модульной структуры должно чётко разграничивать стандартные модули, спецификации которых регулируются Java Community Process, и модули, специфичные для JDK. Оно также должно отделять от всех остальных модулей те модули, которые включены в спецификацию платформы Java SE и тем самым обязательны в каждой реализации платформы.
Мотивация
Цель проекта Jigsaw — спроектировать и реализовать стандартную систему модулей для платформы Java SE и применить эту систему к самой платформе и к JDK. Его основные цели — упростить масштабирование реализаций платформы вплоть до небольших устройств, повысить безопасность и удобство сопровождения, обеспечить более высокую производительность приложений и дать разработчикам более совершенные инструменты для разработки крупных программ.
Описание
Принципы проектирования
Модульная структура JDK реализует следующие принципы:
-
Все остальные модули — просто часть JDK, и их имена начинаются со строки
"jdk.". -
Если модуль экспортирует пакет, содержащий тип, у которого есть public- или protected-член, который, в свою очередь, ссылается на тип из какого-либо другого модуля, то первый модуль должен предоставлять подразумеваемую читаемость (implied readability) второго модуля с помощью
requires transitive. (Так цепочки вызовов методов работают очевидным образом.) -
Стандартный модуль может содержать как стандартные, так и нестандартные пакеты API. Если стандартный модуль экспортирует стандартный пакет API, экспорт может быть квалифицированным; если стандартный модуль экспортирует нестандартный пакет API, экспорт должен быть квалифицированным. В любом случае, если стандартный модуль экспортирует пакет с квалификацией, экспорт должен быть адресован некоторому подмножеству модулей JDK. Если стандартный модуль является модулем Java SE, т. е. включён в спецификацию платформы Java SE, он не должен экспортировать никакие пакеты API, не входящие в SE, по крайней мере без квалификации.
-
Стандартный модуль может зависеть от одного или нескольких нестандартных модулей. Он не должен предоставлять подразумеваемую читаемость какого-либо нестандартного модуля. Если это модуль Java SE, он не должен предоставлять подразумеваемую читаемость какого-либо модуля, не входящего в SE.
-
Нестандартный модуль не должен экспортировать никакие стандартные пакеты API. Нестандартный модуль может предоставлять подразумеваемую читаемость стандартного модуля.
Важное следствие принципов 4 и 5: код, зависящий только от модулей Java SE, будет зависеть только от стандартных типов Java SE и, следовательно, будет переносим на все реализации платформы Java SE.
Граф модулей
Модульную структуру JDK можно представить в виде графа: каждый модуль — вершина, и от одного модуля к другому идёт направленное ребро, если первый зависит от второго. В полном графе модулей слишком много рёбер, чтобы его было удобно отображать; вот транзитивное сокращение графа, в котором избыточные рёбра опущены (нажмите, чтобы увеличить):
Далее — обзор графа модулей:
-
Стандартные модули Java SE окрашены оранжевым; модули, не входящие в SE, — синим.
-
Если один модуль зависит от другого и предоставляет подразумеваемую читаемость этого модуля, ребро от первого модуля ко второму сплошное; в противном случае ребро пунктирное.
-
В самом низу находится модуль
java.base, который содержит основные классы, такие какjava.lang.Objectиjava.lang.String. Базовый модуль не зависит ни от одного модуля, а все остальные модули зависят от базового. Рёбра к базовому модулю светлее остальных рёбер. -
Ближе к верху находится модуль
java.se.ee, который объединяет все модули, составляющие платформу Java SE, включая модули, пересекающиеся со спецификацией платформы Java EE. Это пример агрегирующего модуля, который собирает и повторно экспортирует содержимое других модулей, но не добавляет собственного содержимого. Среда выполнения, сконфигурированная так, чтобы содержать модульjava.se.ee, будет содержать все пакеты API платформы Java SE. Модуль входит в спецификацию платформы Java SE тогда и только тогда, когда это стандартный модуль, достижимый из модуляjava.se.ee. -
Агрегирующий модуль
java.seобъединяет те части платформы Java SE, которые не пересекаются с Java EE. -
К нестандартным модулям относятся инструменты и API для отладки и обслуживания (например,
jdk.jdi,jdk.jcmdиjdk.jconsole), инструменты разработки (например,jdk.compiler,jdk.javadocиjdk.xml.bind) и различные поставщики сервисов (например,jdk.charsets,jdk.scripting.nashornиjdk.crypto.ec), которые становятся доступны другим модулям через существующий механизмjava.util.ServiceLoader. -
Модуль
java.smartcardioстандартный, но не входит в спецификацию платформы Java SE, поэтому его имя начинается со строки"java.", но он окрашен синим и недостижим из модуляjava.se.
Граф модулей фактически представляет собой новый вид API, и его специфицируют и развивают как API. Подграф графа модулей с корнем в модуле java.se.ee, из которого удалены все модули, не входящие в SE, и соответствующие рёбра, определён в спецификации платформы Java SE; его развитие впредь будет регулироваться JCP. Развитие остальной части графа будет описано в будущих JEP. В любом случае, если модуль объявлен доступным для общего использования, на него будут распространяться те же ограничения на развитие, что и на другие API. В частности, удаление такого модуля или его несовместимое изменение потребует публичного уведомления как минимум за один основной выпуск.
Сводная таблица всех модулей, включая показатели занимаемого объёма для сборки Linux/AMD64, доступна здесь.
Тестирование
Модульные и регрессионные тесты в JDK, а также jtreg — средство для их запуска — теперь позволяют выбирать тесты по модулям, которые они тестируют и от которых зависят, так что можно тестировать произвольные конфигурации модулей JDK.
Основной функциональный тест этого улучшения проверяет сконфигурированный набор модулей: что это допустимое сочетание определённых здесь модулей, что каждый модуль имеет ожидаемое содержимое и экспортирует ожидаемые пакеты API и что между модулями существуют ожидаемые зависимости.
Теперь JCK может тестировать те аспекты графа модулей, которые становятся частью спецификации платформы Java SE. Сюда входят имена модулей SE, экспортируемые ими пакеты API и зависимости между ними, из-за которых пакеты API SE повторно экспортируются. JCK также может тестировать произвольные конфигурации модулей SE, присутствующих в реализации платформы.
Риски и допущения
Определённая здесь модульная структура не поддерживает как минимум один известный сценарий использования, а именно использование пакета java.beans без необходимости требовать очень большой модуль java.desktop. Она может не охватывать и другие, пока неизвестные сценарии. Если критически важный сценарий не будет поддержан в окончательной реализации этого JEP, мы рассчитываем, что сможем решить эту проблему в одном из последующих выпусков, переработав граф модулей.
Зависимости
Этот JEP — один из нескольких JEP проекта Jigsaw. Остальные JEP: