Что такое автоматический модуль?
Автоматические модули упоминаются много раз в stackru, но я не смог найти полное, краткое и самодостаточное определение автоматического модуля.
Итак, что такое автоматический модуль? Экспортирует ли он все пакеты? Открывает ли он все пакеты? Читает ли он все остальные модули?
4 ответа
Сначала я отвечу на ваш вопрос ("Что такое автоматический модуль?"), Но я также объясню, для чего они нужны. Трудно понять, почему автоматические модули ведут себя так же, как и без этой информации.
Что такое автоматический модуль?
Система модулей создает модуль из каждого 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 в путь к модулю и требовать его по имени системы модулей. дает это.
Интересным моментом является то, что поскольку автоматические модули читают безымянный модуль, возможно (и я обычно рекомендую это делать) оставить свои зависимости на пути к классам. Таким образом, автоматические модули действуют как мост от модуля к пути класса.
Ваши модули могут находиться на одной стороне, требовать их прямых зависимостей в качестве автоматических модулей, а косвенные зависимости могут оставаться на другой стороне. Каждый раз, когда одна из ваших зависимостей превращается в явный модуль, она оставляет мост на модульной стороне и выводит свои прямые зависимости как автоматические модули на мост.
Автоматический модуль - это именованный модуль, который определяется неявно, так как у него нет объявления модуля. Обычный именованный модуль, напротив, определяется явно, с объявлением модуля; впредь мы будем ссылаться на них как на явные модули.
Основное преимущество их использования заключается в том, что они позволяют обрабатывать артефакт как модуль при компиляции или запуске, не дожидаясь его миграции в модульную структуру.
Имя модуля автоматического модуля получено из файла JAR, который используется для включения артефакта, если он имеет атрибут Automatic-Module-Name в своей основной записи манифеста. В противном случае имя модуля выводится из имени файла JAR ModuleFinder
,
Основываясь на том факте, что автоматический модуль не имеет объявления модуля, практически невозможно определить, какие модули или пакеты он читает, открывает или экспортирует.
➜ Таким образом, поскольку нет явных экспортов / открытий для пакетов, находящихся в автоматическом модуле, описывается как -
... нет практического способа сказать, какие из пакетов в автоматическом модуле предназначены для использования другими модулями или классами, которые все еще находятся на пути к классам. Поэтому каждая упаковка в автоматическом модуле считается экспортируемой, даже если она фактически предназначена только для внутреннего использования.
Further Цитирую ссылку дальше -
... нет практического способа заранее определить, от каких других модулей может зависеть автоматический модуль. Следовательно, после разрешения графа модулей создается автоматический модуль для чтения любого другого именованного модуля, будь то автоматический или явный.
Одно из предложений - автоматический модуль предлагает традиционный уровень инкапсуляции: все пакеты открыты для доступа с глубоким отражением и экспортируются для обычного доступа во время компиляции и во время выполнения к своим общедоступным типам.
➜ Кроме того, автоматический модуль
обеспечивает подразумеваемую читаемость для всех других автоматических модулей
по той причине, что при использовании нескольких автоматических модулей в модуле его
... невозможно определить, содержит ли один из экспортируемых пакетов в автоматическом модуле (xyz) тип, сигнатура которого относится к типу, определенному в каком-то другом автоматическом модуле (abc).
(Вы, похоже, правы насчет отсутствующего полного определения, поскольку я не нашел его в спецификации языка или JVM)
Javadocs дают много формальных определений, хотя в java.lang.module
Пакетные занятия.
Частичная цитата из https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleFinder.html:
Файл 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, он читает каждый безымянный модуль и обрабатывается так, как если бы все пакеты были экспортированы и открыты.
Автоматический модуль — это jar-файл, в котором нет модуля-info.java. Это означает устаревшие файлы jar. Но еще важно то, что он добавляется в MODULE PATH. Таким образом, он рассматривается как модуль с тем же именем, что и файл jar, или именем, указанным в файле манифеста.
Кроме того, для сравнения: весь код и файлы jar в CLASSPATH добавляются в модуль UNNAMED!
Оба неявно экспортируют все общедоступные данные и неявно импортируют все общедоступные данные из других модулей.