Различное поведение программы в 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 шт):

Автор решения: Anton Shchyrov

Нашел проблему. Зависимые библиотеки активно используют 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 эти все файлы будут объединены и все классы обнаружатся в рантайме.

→ Ссылка