Статьи

Что готовит в Java 8 — Jigsaw проекта

Что такое Project Jigsaw: Project Jigsaw — это проект, позволяющий осведомить модуль компилятора java. В течение многих лет Java API был монолитным, то есть весь API был одинаково виден из любой части кода. Также не было никакого способа объявить зависимость кода от любых других пользовательских библиотек. Проект Jigsaw пытается решить эти проблемы вместе с другими очень квалифицированным способом. В этой статье я остановлюсь на основных понятиях модульных систем Jigsaw, а также объясню, как они будут работать с командами, чтобы обеспечить их реальное ощущение. В настоящее время Jigsaw планируется включить в выпуск Java 8. На мой взгляд, это изменение больше, чем дженерики, которые пришли с версией 5 из Java-платформы.

Что достигается проектом Jigsaw: как я объяснил ранее, проект Jigsaw решает проблему использования всего Java-API в качестве единой монолитной кодовой базы. Следующие пункты подчеркивают основные преимущества.

1. График зависимостей : Jigsaw позволяет уникальным образом идентифицировать конкретную кодовую базу, а также объявлять зависимости кодовой базы от других кодовых баз. Это создает полный граф зависимостей для определенного набора классов. Например, вы хотите написать программу, которая зависит от библиотеки Apache BCEL. До сих пор у вас не было возможности выразить это требование в самом коде. Используя Jigsaw, вы можете выразить это требование в самом коде, позволяя инструментам разрешать эту зависимость.

2. Несколько версий одного и того же кода : Предположим, вы пишете программу, которая зависит как от библиотеки A, так и от библиотеки B. Теперь предположим, что библиотека A зависит от версии 1.0 библиотеки C, а библиотека B зависит от версии 2.0 библиотеки C. В текущей версии Java во время выполнения вы не можете использовать библиотеки A и B одновременно, не создавая сложную иерархию пользовательских загрузчиков классов, даже если это не будет работать во всех случаях. После того, как Jigsaw станет частью Java, это не проблема, поскольку класс сможет видеть только версии своих зависимых классов, которые являются частью версий модуля, требуемых модулем контейнера классов. То есть, поскольку модуль A зависит от версии 1.0 модуля C, а модуль B зависит от версии 2.0 модуля C, среда выполнения Java может выяснить, какую версию классов в модуле C следует видеть как модулю A, так и модулю. Б. Это что-то похожее на проект OSGi.

3. Модуляризация самой платформы Java . Текущий API-интерфейс платформы Java огромен, и не все его части могут быть актуальны в каждом случае. Например, платформа Java, предназначенная для запуска сервера Java EE, не должна реализовывать Swing API, поскольку это не имеет никакого смысла. Аналогично, встроенные среды могут сократить некоторые не столь важные API (для встроенных), такие как API компилятора, чтобы сделать его меньше и быстрее. Под текущей платформой Java это невозможно, поскольку любая сертифицированная платформа Java должна реализовывать все API. Jigsaw предоставит способ реализовать только часть набора API, относящуюся к конкретной платформе. Поскольку модуль может явно объявить свою зависимость от какого-либо конкретного Java-модуля API, он будет работать только тогда, когда на платформе есть реализация модулей, запрашиваемых модулем.

4. Интеграция с собственной установкой ОС . Поскольку модульная система очень похожа на ту, которая в настоящее время доступна для установки программ и библиотек в современных операционных системах, java-модули могут быть интегрированы с этими системами. На самом деле они выходят за рамки самого проекта Jigsaw, но поставщикам ОС рекомендуется включить это, и они, скорее всего, сделают это. Например, система репозитория на основе rpm, доступная в системах Linux на основе Redhat, и системы репозиториев на основе apt, доступные в системах Linux на основе Debian, может быть легко расширена для поддержки систем модулей Java.

5. Точка входа в модуль : модули Java могут указывать класс точки входа точно так же, как его могут указать jar-файлы. Когда модуль запущен, вызывается основной метод точки входа. Теперь, поскольку ОС теперь может устанавливать модуль Java, и модуль Java может быть выполнен, это очень похоже на установку собственной программы ОС.

5. Эффективность . Каждый раз, когда JVM запускается, он проверяет целостность каждого отдельного класса, который загружается во время выполнения программы. Это занимает значительное количество времени. Также классы доступны индивидуально из файловой системы ОС. Поскольку модули могут быть установлены до запуска, теперь сама установка может включать в себя этап проверки, который устраняет необходимость проверки классов во время выполнения. Это приведет к значительному улучшению производительности. Кроме того, модульная система может хранить классы по-своему оптимизированно, что приводит к дальнейшему улучшению производительности.

6. Абстракция модуля : можно предоставить абстракцию для конкретного модуля. Скажем, модуль A зависит от модуля X. Теперь модуль D может обеспечить модуль X, тем самым обеспечивая его реализацию. Например, модули Apache Xerces хотели бы предоставить модуль jdk.jaxp и могли бы удовлетворить требование зависимости для jdk.jaxp.

Основы модульной кодовой базы: все вышеприведенные обсуждения довольно расплывчаты без реального примера модульной кодовой базы и ее использования. Модульная кодовая база может быть как одиночной, так и многомодульной. В случае одного модуля все, что нам нужно, чтобы включить модуль, — это создать файл с именем module-info.java в основе исходного пути вне любого пакета. Файл module-info.java представляет собой специальный файл Java, написанный в специальном синтаксисе, предназначенном для объявления информации о модуле. Ниже приведен пример такого mdoule-info.java.

1
2
3
4
5
module com.a @ 1.0{
 
        requires com.b @ 1.0;
        class com.a.Hello;
}

В этом случае модуль называется com.a и имеет зависимость от com.b. Также объявляется точка входа com.a.Hello. Обратите внимание, что не требуется, чтобы структура пакета повторяла имя модуля, хотя это, вероятно, было бы наилучшей практикой.

Теперь вы можете подумать, что если это режим с одним модулем, то почему существует зависимость от другого модуля, разве это не делает его двумя модулями? Обратите внимание, что даже если существует только одно явное объявление модуля зависимостей, существует неявная зависимость от всех модулей java API. Если ни один из модулей API Java не объявлен явно как зависимости, все они включены. Единственная причина, по которой его модуль все еще один, заключается в том, что com.b должен быть доступен в двоичной форме в библиотеке модулей. Это мультимодуль, когда более одного модуля компилируется одновременно. Компиляция источника в одном модуле так же проста, как сборка немодульного источника. Разница лишь в том, что module-info.java будет присутствовать в корневом каталоге.

Многомодульный источник: если источник содержит несколько модулей, им должна быть задана структура каталогов. Это довольно просто, хотя. Источник под конкретным модулем должен храниться в каталоге с именем модуля. Например, источник для класса com.a.Hello в модуле com.a должен храниться в [source-root] /com.a/com/a/Hello.java, а модуль-info.java должен быть сохранен. в каталоге [источник-корень] /com.a

Компиляция многомодульного источника. Для этого рассмотрим пример компиляции двух модулей com.a и com.b. Давайте сначала посмотрим на структуру каталогов. как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
12
classes
src
 |--com.a
 |  |--module-info.java
 |  |--com
 |     |--a
 |        |--Hello.java
 |--com.b
    |--module-info.java
    |--com
       |--b
          |--Printer.java

Код для module-info.java в com.a будет таким:

1
2
3
4
5
module com.a @ 1.0{
 
        requires com.b @ 1.0;
        class com.a.Hello;
}

Модуль-info.java в com.b

1
2
3
module com.b @ 1.0{
        exports com.b;
}

Printer.java в com.b / com / b

1
2
3
4
5
6
7
package com.b;
 
public class Printer{
        public static void print(String toPrint){
                System.out.println(toPrint);
        }
}

Привет.java в com.a / com / a

1
2
3
4
5
6
7
8
package com.a;
import com.b.Printer;
 
public class Hello{
        public static void main(String [] args){
                Printer.print("Hello World!");
        }
}

Коды довольно понятны, мы пытаемся использовать класс com.b.Printer в модуле com.b из класса com.a.Hello в модуле com.a. Для этого необходимо, чтобы com.a module-info.java объявлял com.b как зависимость с ключевым словом require. Мы пытаемся создать выходные файлы классов в каталоге классов. Следующая команда javac сделает это.

1
javac -d classes -modulepath classes -sourcepath src `find src -name '*.java'`

Обратите внимание, что мы использовали команду find в обратных кавычках (`), поэтому выходные данные команды будут включены в список файлов. Это будет работать в среде Linux и Unix. В случае других мы могли бы просто напечатать список файлов.

После компиляции каталог классов будет иметь похожую структуру классов. Теперь мы можем установить модули с помощью команды jmod.

1
2
3
jmod create -L mlib
jmod install -L mlib classes com.b
jmod install -L mlib classes com.a

Сначала мы создали библиотеку модулей mlib и установили наши модули в библиотеку. Мы также могли бы использовать библиотеку по умолчанию, не указав параметр -L для команды установки в jmod.

Теперь мы можем просто запустить модуль com.a, используя

1
java -L mlib -m com.a

Здесь также мы могли бы использовать модуль по умолчанию. Также возможно создать пакет распространяемого модуля [эквивалент jar в современном механизме распространения], который можно установить напрямую. Например, следующее создаст [email protected] для com.a

1
jpkg -m classes/com.a jmod com.a

Я попытался обрисовать в общих чертах инфраструктуру модуля в следующем выпуске Java. Тем не менее, проект Jigsaw меняется каждый день, и в конце может оказаться совершенно другим существом. Но ожидается, что основные концепции останутся прежними. Общие концепции модулей более сложны, и я подробно расскажу о них в следующей статье.

Ссылка: Что готовит в Java 8 — Проект Jigsaw от нашего партнера по JCG Дебасиш Рэй Чаудхури в блоге Geeky Articles .