В качестве аргумента давайте предположим, что Java 8 (и более ранние версии) уже имеет «форму» модулей (jar-файлов) и модульную систему (путь к классам). Но с этим есть известные проблемы.
Изучая проблемы, мы можем проиллюстрировать мотивацию Jigsaw. (Ниже предполагается, что мы не используем OSGi, JBoss Modules и т. Д., Которые, безусловно, предлагают решения.)
Проблема 1: публично слишком публично
Рассмотрим следующие классы (предположим, что оба являются общедоступными):
com.acme.foo.db.api.UserDao
com.acme.foo.db.impl.UserDaoImpl
В Foo.com мы можем решить, что наша команда должна использовать, UserDao
а не использовать UserDaoImpl
напрямую. Однако нет никакого способа принудительно применить это в пути к классам.
В Jigsaw модуль содержит module-info.java
файл, который позволяет нам явно указывать, что является общедоступным для других модулей. То есть у публики есть нюанс. Например:
module com.acme.foo.db {
exports com.acme.foo.db.api;
}
Проблема 2: отражение необузданно
Учитывая классы в # 1, кто-то все еще может сделать это в Java 8:
Class c = Class.forName("com.acme.foo.db.impl.UserDaoImpl");
Object obj = c.getConstructor().newInstance();
То есть: отражение - мощное и важное средство, но, если его не остановить, оно может использоваться для проникновения во внутреннее устройство модуля нежелательными способами. У Марка Рейнхольда есть довольно тревожный пример . (Сообщение SO здесь .)
В Jigsaw сильная инкапсуляция дает возможность запретить доступ к классу, включая отражение. (Это может зависеть от настроек командной строки в ожидании пересмотренной технической спецификации для JDK 9.) Обратите внимание, что поскольку Jigsaw используется для самого JDK, Oracle утверждает, что это позволит команде Java быстрее внедрять инновации во внутреннее устройство платформы.
Проблема 3: путь к классам стирает архитектурные связи
У команды обычно есть ментальная модель взаимоотношений между банками. Например, foo-app.jar
может использовать то, foo-services.jar
что использует foo-db.jar
. Мы можем утверждать, что классы foo-app.jar
не должны обходить «уровень обслуживания» и использовать их foo-db.jar
напрямую. Однако нет способа принудительно применить это через путь к классам. Марк Рейнхольд упоминает об этом здесь .
Для сравнения, Jigsaw предлагает явную и надежную модель доступности для модулей.
Проблема 4: монолитная среда выполнения
Среда выполнения Java является монолитной rt.jar
. На моей машине это 60+ МБ с 20к классов! В эпоху микросервисов, устройств IoT и т. Д. Нежелательно иметь на диске Corba, Swing, XML и другие библиотеки, если они не используются.
Jigsaw разбивает сам JDK на множество модулей; например, java.sql содержит знакомые классы SQL. У этого есть несколько преимуществ, но новый jlink
инструмент - это инструмент. Предполагая, что приложение полностью модульное, jlink
генерирует распространяемый образ времени выполнения, который обрезан, чтобы содержать только указанные модули (и их зависимости). Забегая вперед, Oracle предвидит будущее, в котором модули JDK будут заранее скомпилированы в собственный код. Хотя jlink
это необязательно, а компиляция AOT является экспериментальной, они являются основными показателями того, куда движется Oracle.
Проблема 5: управление версиями
Хорошо известно, что путь к классам не позволяет нам использовать несколько версий одного и того же jar-файла: например, bar-lib-1.1.jar
и bar-lib-2.2.jar
.
Jigsaw не решает эту проблему; Марк Рейнхольд излагает здесь обоснование . Суть в том, что Maven, Gradle и другие инструменты представляют собой большую экосистему для управления зависимостями, и другое решение будет скорее вредным, чем полезным.
Следует отметить, что другие решения (например, OSGi) действительно решают эту проблему (и другие, кроме №4).
Нижняя граница
Это некоторые ключевые моменты для Jigsaw, мотивированные конкретными проблемами.
Обратите внимание, что объяснение противоречий между Jigsaw, OSGi, JBoss Modules и т. Д. - это отдельное обсуждение, которое принадлежит другому сайту Stack Exchange. Между решениями гораздо больше различий, чем описано здесь. Более того, был достигнут достаточный консенсус для утверждения бюллетеня для повторного рассмотрения с общественностью для JSR 376.