Различное поведение программы в IDEA и jar
Есть проект с большими зависимостями (работаю с helidon). При запуске из IDEA все работает отлично. При сборке проекта через mvn package и последующим java -jar myproject.jar начинают вылазить всякие баги. Как я понимаю, баги вылазят из-за того, что в результирующий jar не попадают какие-то классы из зависимостей (или classloader не может их найти, потому что в jar файле я их, вроде, вижу).
При указании разных зависимостей, например, других версий или других пакетов, теряются разные классы.
Например, сейчас не загружается парсер yaml конфига. Хотя файл YamlConfigParser.class лежит в jar файле
В IDEA явно никаких зависимостей и настроек не прописывал. Все лежит в pom.xml
Вопрос - что происходит и откуда разное поведение?
Кстати, еще бывают ситуации, что jar собирается, а IDEA не может откомпилировать проект. Говорит, что не найдены классы.
Не знаю, относится к теме или нет, но при сборке maven появляется куча сообщений
[WARNING] Discovered module-info.class. Shading will break its strong encapsulation.
Сборка производится maven-shade-plugin
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.Loader</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
</build>
Если jar-файл создавать в IDEA через Build Artifacts, то все работает.
Сравнил два jar-файла от IDEA и maven. Классы одни и те же. В версии от IDEA в корне дополнительно лежит module-info.class и очень сильно различается содержимое папки META-INF
Ответы (1 шт):
Нашел проблему. Зависимые библиотеки активно используют ServiceLoader и динамическую загрузку классов. Информация о том, какие классы загружать складывается в файлы в папке META-INF/services.
Плагин maven-shade-plugin по умолчанию помещает в итоговый jar первый попавшийся файл из META-INF/services зависимых модулей. Но если плагину указать трансформер org.apache.maven.plugins.shade.resource.ServicesResourceTransformer
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.Loader</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
то тогда при обнаружении в зависимых модулях в папке META-INF/services файлов с одинаковым именем, в конечном jar эти все файлы будут объединены и все классы обнаружатся в рантайме.