Модульный jar-файл

Последнее обновление: 06.11.2025

Упаковка функционала пакетов в единый jar-файл также может использоваться для распространения модулей Java. JAR-файл, который по сути представляет скомпилированный модуль, называется модульным JAR-файлом.

Для создания модульного JAR-файла аналогичным образом применяется утилита jar. Если модуль содержит несколько пакетов, то также лучше всего его компилировать с опцией -d, которая помещает файлы классов в отдельный каталог (если каталог еще не существует, то он создается). А при упаковке файлов в jar-файл для перехода в этот каталог применяется опция -C команды jar. Рассмотрим на примере.

Определение модуля

Для начала где-нибудь на жестком диске (в моем случае это папка worlspace/java) создадим каталог, который назовем demo. Этот каталог будет представлять одноименный модуль. И в этом каталоге demo определим новый файл module-info.java - файл дескриптора модуля со следующим кодом:

module demo {
}

Далее в каталоге demo создадим папку com. В папке com создадим папку metanit, а в папке com/metanit - папку hello.

В папке com/metanit/hello определим новый файл Hello.java:

package com.metanit.hello;
 
public class Hello{
     
    public static void main(String[] args){
        System.out.println("Hello METANIT.COM!");
    }
}

Название пакета файла - com.metanit.hello отражает структуру папок, в которых расположен файл. Сам файл определяет класс Hello, который в методе main выводит на консоль строку.

В итоге у нас получится следующая стуктура проекта:

Модули в Java

Теперь скомпилируем все это и упакуем в файл jar.

Создание jar

Для создания jar перейдем в командной строке/терминале к папке, где находится папка demo с нашим модулем (в моем случае это папка worlspace/java). Затем для компиляции модуля выполним следующую команду:

javac --module-source-path . -d mods demo/module-info.java demo/com/metanit/hello/Hello.java

После компиляции модуля в текущей папке появится папка "mods", в которую будут помещаться все скомпилированные классы модуля demo и которая будет иметь следующую структуру:

mods
|_demo
    |_module-info.class
    |_com
        |_metanit
            |_hello
                |_Hello.class

Далее для упаковки в jar выполним следующую команду:

jar -c -v -f demo.jar -C mods/demo .

Команда принимает следующие параметры

  • -c: указывает на создание нового архива.

  • -v: предоставляет подробный вывод выполнения команды

  • -f demo.jar: задает имя создаваемого JAR-файла. То есть создаваемый файл будет называться "demo.jar"

  • -C mods/demo .: переходит в папку с скомпилированными классами (mods/имя__модуля) и добавляет все ее содержимое (.) в JAR. В данном случае это папка "mods" (название произвольное) и ее подкаталог "demo", название которого должно соответствовать имени модуля, указананного в module-info.java (если указано). В примере выше модуль называется "demo", соответственно все компилируемые файлы помещаются в папку "mods/demo"

Полный консольный вывод:

eugene@Eugene:~$ cd workspace/java
eugene@Eugene:/workspace/java$ javac --module-source-path . -d mods demo/module-info.java demo/com/metanit/hello/Hello.java
eugene@Eugene:/workspace/java$ jar -c -v -f demo.jar -C mods/demo .
added manifest
added module-info: module-info.class
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/Hello.class(in = 440) (out= 305)(deflated 30%)
eugene@Eugene:/workspace/java$ 

Создание исполняемого jar

Но в примере выше класс Hello является исполняемым, то есть он имеет метод main() и может быть запущен на выполнение. И как и в обычных JAR-файлах, в модульном JAR-файле можно указать основной класс, который будет выполняться при запуске. Для этого предназначена опция -e (полное название опции - --main-class), которой передается название основного класса с учетом его пакетов:

jar -c -v -f demo.jar -e com.metanit.hello.Hello -C mods/demo .

В примере выше класс Hello определен в пакете com.metanit.hello, поэтому указываем в качестве полного имени файла "com.metanit.hello.Hello".

После этого можно запустить созданный модульный JAR-файл с помощью команды java:

java --module-path demo.jar --module demo

Полный консольный вывод:

eugene@Eugene:/workspace/java$ javac --module-source-path . -d mods demo/module-info.java demo/com/metanit/hello/Hello.java
eugene@Eugene:/workspace/java$ jar -c -v -f demo.jar -e com.metanit.hello.Hello -C mods/demo .
added manifest
added module-info: module-info.class
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/Hello.class(in = 440) (out= 305)(deflated 30%)
eugene@Eugene:/workspace/java$ java --module-path demo.jar --module demo
Hello METANIT.COM!
eugene@Eugene:/workspace/java$ 

Компиляция взаимодействующих модулей

Рассмотрим другую, более сложную ситуацию, где у нас есть несколько модулей, которые взаимодействуют друг с другом. Допустим, у нас есть следующая структура проектов:

Взаимодействие модулей в Java

Здесь определено два модуля: demo и operations. Каждый располагается в своей одноименной папке.

В папке operations/com/metanit/factorial определен следующий файл Factorial.java:

package com.metanit.factorial;

public class Factorial{
	
	public static int calculate(int n){
		if (n < 1) return -1;
        int result = 1;
        while (n > 1) result *= n--;
        return result;
	}
}

Класс Factorial определяет функцию вычисления факториала и принадлежит пакету com.metanit.factorial.

Чтобы сделать этот класс и в целом его пакет доступным для использования в других модулях в папке operations определен следующий файл module-info.java:

module operations {
    exports com.metanit.factorial;
}

В папке demo определен следующий файл module-info.java:

module demo {
    requires operations;
}

С помощью оператора requires< указываем, что модуль demo будет использовать модуль operations.

А в папке demo/com/metanit/hello/ определим следующий файл Hello.java:

package com.metanit.hello;

import com.metanit.factorial.Factorial;

public class Hello{
	
	public static void main(String[] args){
		
		int a = 5;
		int b = Factorial.calculate(a);
		System.out.printf("Factorial of %d is equal to %d \n", a, b);
	}
}

Здесь мы подключаем класс Factorial из пакета "com.metanit/factorial" и вычисляем факториал числа.

Теперь нам надо оба модуля скомпилировать в jar-файлы. Стандартный подход предполагает, что оба модуля компилируются по отдельности каждый в свой jar-файл. В консоли перейдем к корневой папке, где размещаются оба модуля (в моем случае это папка "/workspace/java") и скомпилируем их. Для этого выполним следующую команду:

javac --module-source-path . -d mods demo/module-info.java demo/com/metanit/hello/Hello.java

Хотя здесь указан только один модуль, зависимый модуль также будет скомпилирован. Оба модуля в данном случае будут помещаться в папку "mods", которая в итоге будет иметь следующую структуру:

mods
|_demo
|   |_module-info.class
|   |_com
|       |_metanit
|           |_hello
|                |_Hello.class
|_factorial
    |_module-info.class
    |_com
        |_metanit
            |_factorial
                |_Factorial.class

Далее скомпилируем модуль operations:

jar -c -v -f libs/operations.jar -C mods/operations .

Компилируем из модуля файл "operations.jar" будет помещаться в папку "libs". Далее скомпилируем модуль demo:

jar -c -v -f libs/demo.jar -e com.metanit.hello.Hello -C mods/demo .

В итоге в папке "libs" будут располагаться оба скомпилированных модуля. Теперь запустим главный модуль, передав путь к папке с модульными jar:

java --module-path libs --module demo/com.metanit.hello.Hello

Полный консольный вывод:

eugene@Eugene:/workspace/java$ javac --module-source-path . -d mods demo/module-info.java demo/com/metanit/hello/Hello.java
eugene@Eugene:/workspace/java$ jar -c -v -f libs/operations.jar -C mods/operations .
added manifest
added module-info: module-info.class
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/factorial/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/factorial/Factorial.class(in = 339) (out= 266)(deflated 21%)
eugene@Eugene:/workspace/java$ jar -c -v -f libs/demo.jar -e com.metanit.hello.Hello -C mods/demo .
added manifest
added module-info: module-info.class
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/(in = 0) (out= 0)(stored 0%)
adding: com/metanit/hello/Hello.class(in = 660) (out= 421)(deflated 36%)
eugene@Eugene:/workspace/java$ java --module-path libs --module demo/com.metanit.hello.Hello
Factorial of 5 is equal to 120 
eugene@Eugene:/workspace/java$ 
Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850
Morty Proxy This is a proxified and sanitized view of the page, visit original site.