Виконуваний формат Jar

Модулі spring-boot-loader дозволяють Spring Boot підтримувати виконувані файли jar та war. Якщо ви використовуєте плагін Maven або плагін Gradle, виконувані банки генеруються автоматично, і вам, як правило, не потрібно знати подробиці того, як вони працюють.

Spring Boot

Якщо вам потрібно створити виконувані банки з іншої системи збірки, або якщо вам просто цікаво, що лежить в основі технології, цей додаток містить деяку довідкову інформацію.

1. Вкладені JAR

Java не забезпечує жодного стандартного способу завантаження вкладених файлів jar (тобто файлів jar, які самі містяться в jar). Це може бути проблематично, якщо вам потрібно розповсюдити автономну програму, яку можна запустити з командного рядка без розпакування.

Для вирішення цієї проблеми багато розробників використовують «затінені» банки. Заштрихована банка упаковує всі класи, з усіх банок, в одну «банку uber». Проблема затінених банок полягає в тому, що стає важко зрозуміти, які бібліотеки насправді є у вашому додатку. Це також може бути проблематично, якщо в декількох банках використовується одне і те ж ім'я файлу (але з різним вмістом). Spring Boot використовує інший підхід і дозволяє вам фактично гніздити банки безпосередньо.

1.1. Структура файлу виконуваного файлу Jar

Файли jar, сумісні з Spring Boot Loader, повинні бути структуровані таким чином:

Класи додатків слід розміщувати у вкладеному каталозі BOOT-INF/classes. Залежності слід розміщувати у вкладеному каталозі BOOT-INF/lib.

1.2. Структура файлів, що виконуються

Військові файли, сумісні з Spring Boot Loader, повинні бути структуровані таким чином:

Залежності слід розміщувати у вкладеному каталозі WEB-INF/lib. Будь-які залежності, які потрібні при запуску вбудованого, але не потрібні при розгортанні в традиційному веб-контейнері, слід розміщувати у WEB-INF/lib .

1.3. Індексні файли

Архіви jar і war, сумісні з Spring Boot Loader, можуть включати додаткові файли індексу в каталог BOOT-INF /. Файл classpath.idx може бути наданий як для банок, так і для війн, він забезпечує порядок додавання банок до шляху до класу. Файл layer.idx можна використовувати лише для банок, він дозволяє розділити банку на логічні шари для створення зображення Docker/OCI.

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

1.4. Індекс шляху до класу

Індексний файл classpath можна надати в BOOT-INF/classpath.idx. Він надає список назв jar (не включаючи каталог) у тому порядку, в якому їх слід додати до шляху до класу. Кожен рядок повинен починатися з пробілу ("- ·"), а імена повинні бути в подвійних лапках.

Наприклад, враховуючи таку банку:

Файл індексу буде виглядати так:

1.5. Індекс шару

Файл індексів шарів можна надати в BOOT-INF/layer.idx. Він надає перелік шарів та частин банки, які повинні міститися в них. Шари записуються в тому порядку, що їх слід додати до образу Docker/OCI. Назви шарів записуються у вигляді рядків із лапками, префіксом яких є пробіл ("- ·") та суфіксом двокрапки (":") Вміст шару - це або файл, або ім'я каталогу, записане як рядок із цитуваннями, префіксом якого є пробіл тире пробіл ("·· - ·"). Ім'я каталогу закінчується на /, ім'я файлу - ні. Коли використовується ім'я каталогу, це означає, що всі файли всередині цього каталогу знаходяться в одному шарі.

Типовим прикладом індексу шарів може бути:

2. Клас “JarFile” Spring Boot

Основним класом, що використовується для підтримки завантаження вкладених банок, є org.springframework.boot.loader.jar.JarFile. Це дозволяє завантажувати вміст jar зі стандартного файлу jar або із вкладених даних дочірнього jar. При першому завантаженні розташування кожного JarEntry відображається у зсув фізичного файлу зовнішньої банки, як показано в наступному прикладі:

Попередній приклад показує, як A.class можна знайти в/BOOT-INF/класах у myapp.jar у позиції 0063. B.class із вкладеної банки насправді можна знайти в myapp.jar у позиції 3452, а C.class - у позиції 3980 .

Озброївшись цією інформацією, ми можемо завантажувати конкретні вкладені записи, шукаючи відповідну частину зовнішньої банки. Нам не потрібно розпаковувати архів, і нам не потрібно читати всі введені дані в пам’ять.

2.1. Сумісність зі стандартною Java “JarFile”

Spring Boot Loader прагне залишатися сумісним із існуючим кодом та бібліотеками. org.springframework.boot.loader.jar.JarFile поширюється від java.util.jar.JarFile і повинен працювати як заміна. Метод getURL () повертає URL-адресу, яка відкриває підключення, сумісне з java.net.JarURLConnection, і може використовуватися з URL-адресою JavaClassLoader .

3. Запуск виконуваних банок

Клас org.springframework.boot.loader.Launcher - це спеціальний клас завантажувальної стрічки, який використовується як основна точка входу виконуваної банки. Це фактичний Main-Class у вашому файлі jar, і він використовується для налаштування відповідного URLClassLoader і в кінцевому підсумку викликає ваш метод main ().

Є три підкласи панелі запуску (JarLauncher, WarLauncher та PropertiesLauncher). Їх мета - завантажувати ресурси (файли .class тощо) із вкладених файлів jar або файлів війни в каталоги (на відміну від явно вказаних у шляху до класу). У разі JarLauncher і WarLauncher вкладені шляхи виправлені. JarLauncher виглядає в BOOT-INF/lib /, а WarLauncher виглядає в WEB-INF/lib/та WEB-INF/lib-provided /. Ви можете додати додаткові банки в цих місцях, якщо хочете більше. За замовчуванням PropertiesLauncher виглядає в BOOT-INF/lib/в архіві вашої програми. Ви можете додати додаткові розташування, встановивши змінну середовища з назвою LOADER_PATH або loader.path у loader.properties (це розділений комами список каталогів, архівів або каталогів у архівах).

3.1. Маніфест пускової установки

Вам потрібно вказати відповідний Launcher як атрибут основного класу META-INF/MANIFEST.MF. Фактичний клас, який ви хочете запустити (тобто клас, що містить основний метод), слід вказати в атрибуті Start-Class.

У наступному прикладі показано типовий MANIFEST.MF для виконуваного файлу jar:

Для файлу війни це буде так:

4. PropertiesLauncher Особливості

PropertiesLauncher має кілька спеціальних функцій, які можна активувати за допомогою зовнішніх властивостей (властивості системи, змінні середовища, записи маніфесту або loader.properties). Наступна таблиця описує ці властивості:

Шлях до класів, відокремлений комами, наприклад lib, $/app/lib. Ранні записи мають пріоритет, як звичайний -classpath у командному рядку javac.

Використовується для вирішення відносних шляхів у loader.path. Наприклад, якщо вказано loader.path = lib, тоді $/lib - це розташування шляху до класу (разом із усіма файлами jar в цьому каталозі). Ця властивість також використовується для пошуку файлу loader.properties, як у наступному прикладі/opt/app За замовчуванням $ .

Аргументи за замовчуванням для основного методу (з пробілом).

Назва основного класу для запуску (наприклад, com.app.Application).

Назва файлу властивостей (наприклад, панель запуску). За замовчуванням завантажувач .

Шлях до файлу властивостей (наприклад, classpath: loader.properties). За замовчуванням loader.properties .

Логічний прапор, що вказує на те, що всі властивості слід додавати до властивостей системи. За замовчуванням значення false .

Якщо вони вказані як змінні середовища або записи маніфесту, слід використовувати такі імена:

Для роботи з PropertiesLauncher застосовуються такі правила:

loader.properties шукається в loader.home, потім у кореневій частині шляху до класу, а потім у classpath:/BOOT-INF/classes. Перше місце, де існує файл із таким іменем, використовується.

loader.home - розташування каталогу додаткового файлу властивостей (замінює за замовчуванням) лише тоді, коли loader.config.location не вказано.

loader.path може містити каталоги (які рекурсивно перевіряються на наявність jar та zip-файлів), шляхи архівування, каталог в архіві, який перевіряється на файли jar (наприклад, dependencies.jar!/lib), або шаблони підстановки (для поведінка JVM за замовчуванням). Шляхи архіву можуть бути відносно loader.home або де-небудь у файловій системі з префіксом jar: file:.

loader.path (якщо порожній) за замовчуванням є BOOT-INF/lib (мається на увазі локальний каталог або вкладений, якщо він працює з архіву). Через це PropertiesLauncher поводиться так само, як JarLauncher, коли додаткова конфігурація не передбачена.

loader.path не можна використовувати для налаштування розташування loader.properties (шлях до класу, який використовується для пошуку останнього, - це шлях до класу JVM при запуску PropertiesLauncher).

Заміна заповнювача виконується із змінних системи та середовища плюс самого файлу властивостей для всіх значень перед використанням.

Порядок пошуку властивостей (де має сенс шукати більше ніж в одному місці) - це змінні середовища, властивості системи, loader.properties, маніфест розгорнутого архіву та маніфест архіву.

5. Виконувані обмеження Jar

Потрібно враховувати такі обмеження під час роботи із пакетом Spring Boot Loader:

Стиснення записів Zip: ZipEntry для вкладеної банки потрібно зберегти за допомогою методу ZipEntry.STORED. Це потрібно для того, щоб ми могли шукати безпосередньо окремий вміст у вкладеному jar. Вміст самого вкладеного файлу jar все ще може бути стиснений, як і будь-які інші записи у зовнішньому jar.

Системний класLoader: Запущені програми повинні використовувати Thread.getContextClassLoader () під час завантаження класів (більшість бібліотек та фреймворків роблять це за замовчуванням). Не вдається завантажити вкладені класи jar за допомогою ClassLoader.getSystemClassLoader (). java.util.Logging завжди використовує системний завантажувач класів. З цієї причини слід розглянути іншу реалізацію ведення журналу.

6. Альтернативні рішення з однобаночним посудом

Якщо попередні обмеження означають, що ви не можете використовувати Spring Boot Loader, розгляньте такі альтернативи: