Mavenにおける依存関係統合型JAR(Fat JAR)のパッケージング手法

Mavenにおけるデフォルトのビルド産出物は標準JARと呼ばれ、コンパイル済みのバイトコード(.class)とそのプロジェクト固有のリソースのみを含む軽量の包みです。依存性解決の結果であるサードパーティ製ライブラリは一切含まれないため、他のモジュールからの参照対象としては理想的ですが、独立したプロセスとして起動することはできません。容量も通常は数キロバイト程度に抑えられます。

これに対して、Fat JAR(実行可能JARまたはUber JAR)は、アプリケーションを単独でデプロイ・実行可能な形態に再構築したものです。spring-boot-maven-pluginの機能により、プロジェクト本体のクラスファイル、すべての依存ライブラリ、そして内蔵Webサーバー(Tomcatなど)や起動フレームワークを含む「完全な実行環境」が一個のファイルに圧縮されます。数百メガバイトを超えるサイズになることもありますが、java -jar target/app-exec.jarというシンプルなコマンドで即座にサービスを開始できるため、マイクロサービスやコンテナネイティブな開発において標準的な選択肢となっています。

Fat JARの内部構造

作成されたアーカイブを展開すると、以下のような独自の階層構造でリソースが整理されているのが特徴です。

├── BOOT-INF                     // アプリケーション本体と解決された依存ライブラリの格納庫
│   ├── classes                  // コンパイル済み.classファイルとapplication.yml等の静的リソース
│   └── lib                      // pom.xmlで宣言された全依存モジュール(依存解決後のJAR群)
├── META-INF                     // JARメタデータ管理ディレクトリ
│   └── MANIFEST.MF              // JVM向けの起動情報(Main-Class、カスタムClassPath設定など)
└── org
    └── springframework
        └── boot
            └── loader           // FAT-JAR専用のクラスローダーとリソース読み込みロジック

通常、Java VMはMANIFEST.MFに定義されたクラスパスのみを参照しますが、Spring BootはBOOT-INF配下の階層的かつ動的なリソース解決を実現するために、独自の実装を持つboot.loaderパッケージを利用しています。

pom.xmlでのビルド定義例

上記のパッケージング動作を実現するには、プロジェクトルートにあるpom.xmlにコンパイラ仕様とプラグイン実行ルールを登録します。構成の変更に柔軟に対応できるよう、プロパティ管理を活用しつつ、必要なフェーズとゴールを設定したサンプルを示します。

<properties>
    <maven.compiler.version>3.11.0</maven.compiler.version>
    <springboot.maven.plugin.version>3.2.1</springboot.maven.plugin.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <jdk.version>17</jdk.version>
</properties>

<build>
    <plugins>
        <!-- コンパイル時のJVM環境を規定 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>&{maven.compiler.version}</version>
            <configuration>
                <release>&{jdk.version}</release>
                <encoding>&{project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>

        <!-- Spring Boot実行環境への変更 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>&{springboot.maven.plugin.version}</version>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
            <executions>
                <execution>
                    <id>bootstrap-runtime</id>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                    <configuration>
                        <classifier>launch</classifier>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <finalName>service-core</finalName>
</build>

この設定では、コンパイル環境とプラグインのバージョンをプロパティで一元管理し、不要なランタイム依存(例:Lombok)を除外リストに追加しています。repackageゴールを実行することで、原本のJARファイルに加えて-launch.jarという接尾辞付きの実行可能ファイルが生成されます。これにより、デプロイスクリプト側でファイルの判別が容易になり、依存関係の整合性チェックもスムーズに行えます。

タグ: Maven spring-boot jar-packaging fat-jar pom-config

7月29日 05:37 投稿