Что такое автоматический модуль?

Автоматические модули много раз упоминаются в stackoverflow, но я не смог найти полного, сжатого и самодостаточного определения автоматического модуля.

Итак, что такое автоматический модуль? Все пакеты экспортируются? Открывает ли он все пакеты? Все остальные модули читает?


person ZhekaKozlov    schedule 14.10.2017    source источник


Ответы (3)


Я сначала отвечу на ваш вопрос («Что такое автоматический модуль?»), Но я также объясню, для чего они нужны для. Трудно понять, почему автоматические модули ведут себя именно так, без этой информации.

Что такое автоматический модуль?

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

Имя

Получение названия - это двухэтапный процесс:

  • если JAR определяет заголовок Automatic-Module-Name в своем манифесте, он определяет имя модуля
  • в противном случае имя файла JAR используется для определения имени

Второй подход изначально нестабилен, поэтому не следует публиковать модули, зависящие от такого автоматического модуля. Maven предупреждает об этом.

Требует

Поскольку простой JAR выражает предложения, не требующие выполнения, система модулей позволяет автоматическим модулям читать все другие модули, которые попадают в график читабельности (также известный как график модулей). В отличие от явных модулей, автоматические также читают безымянный модуль, который содержит все, что было загружено из пути к классам. Эта, казалось бы, второстепенная деталь оказывается очень важной (см. Ниже).

Однако у автоматических модулей есть и другие особенности читабельности:

  • Как только будет разрешен первый автоматический модуль, будут разрешены все остальные. Это означает, что как только на один простой JAR в пути к модулю ссылается другой модуль, все простые JAR загружаются как автоматические модули.
  • Автоматические модули подразумевают удобочитаемость всех других автоматических модулей, что означает, что модуль читает один из них. , читает их все.

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

Экспорт / Открытие

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

Более

Система модулей также сканирует META-INF/services и заставляет автоматический модуль предоставлять указанные в нем услуги. Предполагается, что автоматическому модулю разрешено использовать все службы.

Наконец, запись манифеста Main-Class также обрабатывается, поэтому простой JAR, определяющий ее, может быть запущен точно так же, как автоматический модуль, в котором основной класс был установлен с помощью инструмента jar (т.е. java --module-path my-app.jar --module my.app).

Правильный модуль

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

Что такое автоматический модуль для?

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

Чтобы обеспечить их надежность, объявление модуля не может требовать чего-либо, кроме именованного модуля, который исключает все загруженное из пути к классу. Если бы история на этом закончилась, модульный JAR мог бы зависеть только от других модульных JAR, что заставило бы экосистему модулироваться снизу вверх.

Однако это неприемлемо, поэтому автоматические модули были введены как средство для зависимости модульных JAR от немодульных, и все, что вам нужно для этого, - это разместить простой JAR на пути к модулю и потребовать его по имени модульная система. дает это.

Интересно то, что, поскольку автоматические модули читают безымянный модуль, возможно (и я обычно рекомендую это делать) оставить его зависимости на пути к классу. Таким образом, автоматические модули действуют как мост от модуля к пути к классу.

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

person Nicolai Parlog    schedule 14.10.2017
comment
Этот вопрос SO дает некоторую полезную информацию в отношении фактически настраивая ваш проект на использование автоматического модуля. - person JMess; 25.01.2018
comment
Вы знаете, запрещают ли автоматические модули разделение пакетов или нет? Думаю, об этом стоит упомянуть в ответе. - person ZhekaKozlov; 25.05.2018
comment
Включил его в Правильный модуль. - person Nicolai Parlog; 27.05.2018

автоматический модуль - это именованный модуль, который определяется неявно, поскольку он не имеет объявления модуля. Обычный именованный модуль, напротив, определяется явно с помощью объявления модуля; в дальнейшем мы будем называть их явными модулями.

Основное преимущество их использования заключается в том, что они позволяют рассматривать артефакт как модуль при компиляции или запуске, не дожидаясь его миграции в модульную структуру.

Имя модуля автоматического модуля происходит из файла JAR, который используется для включения артефакта, если он имеет атрибут Automatic-Module-Name в его основной записи манифеста. В противном случае имя модуля получается из имени файла JAR с помощью _ 1_.


Исходя из того факта, что автоматический модуль не имеет объявления модуля, практически невозможно сказать, какие все модули или пакеты он читает, открывает или экспортирует.

➜ Итак, поскольку нет явного экспорта / открытия для пакетов, находящихся в автоматическом модуле, описанном как -

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

➜ Цитируя ссылку дальше -

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

Одно из предложений - An автоматический модуль предлагает традиционный уровень инкапсуляции: Все пакеты открыты для глубокого рефлексивного доступа и экспортируются для обычного доступа во время компиляции и выполнения к их общедоступным типы.


➜ Дополнительно автоматический модуль

обеспечивает подразумеваемую удобочитаемость для всех других автоматических модулей

по той причине, что при использовании нескольких автоматических модулей в модуле его

..не возможно определить, содержит ли один из экспортированных пакетов в автоматическом модуле (x.y.z) тип, сигнатура которого относится к типу, определенному в каком-то другом автоматическом модуле (a.b.c).

person Naman    schedule 14.10.2017

(Вы, кажется, правы насчет отсутствия полного определения, поскольку я не нашел его в спецификациях языка или JVM)

Документация Javadocs предоставляет множество формальных определений в классах пакетов java.lang.module.

Частичная цитата из https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleFinder.html#automatic-modules:

Файл JAR, не имеющий module-info.class в каталоге верхнего уровня, определяет автоматический модуль следующим образом:

  • Если файл JAR имеет атрибут Automatic-Module-Name в своем основном манифесте, то его значением является имя модуля. В противном случае имя модуля является производным от имени файла JAR.

...

И из https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleDescriptor.html:

Дескриптор модуля для автоматического модуля не объявляет никаких зависимостей (кроме обязательной зависимости от java.base) и не объявляет никаких экспортированных или открытых пакетов. Автоматические модули получают особую обработку во время разрешения, так что они читают все другие модули в конфигурации. Когда автоматический модуль создается на виртуальной машине Java, он считывает каждый безымянный модуль и обрабатывается так, как если бы все пакеты были экспортированы и открыты.

ИЗМЕНИТЬ (2021 г.):

Этот раздел о зависимостях модулей из спецификации языка Java содержит следующие интересные примечания:

Платформа Java SE различает именованные модули, которые явно объявлены (то есть с объявлением модуля), и именованные модули, которые неявно объявлены (то есть автоматические модули). Однако в языке программирования Java различие не обнаруживается: директивы requires относятся к именованным модулям независимо от того, объявлены они явно или неявно.

Хотя автоматические модули удобны для миграции, они ненадежны в том смысле, что их имена и экспортированные пакеты могут измениться, когда их авторы конвертируют их в явно объявленные модули. Компилятору Java рекомендуется выдавать предупреждение, если директива requires относится к автоматическому модулю. Особенно строгое предупреждение рекомендуется, если в директиве присутствует модификатор транзитивности.

person M A    schedule 14.10.2017