Javaででビルドする際に,開発したプログラムだけでなく,依存しているjarも含めてすべてを単一のjarファイルにまとめたい時の方法について紹介します.
目次
ライブラリのクラスパス
Mavenで作成したプロジェクトで依存関係のあるライブラリを指定した場合、以下で起動しようとすると、依存しているライブラリのクラスパスが見つからないとエラーが表示されます。
% java -jar ./target/DirectoryMerge-1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: gnu/getopt/Getopt
at org.example.DirectoryMerge.main(DirectoryMerge.java:33)
Caused by: java.lang.ClassNotFoundException: gnu.getopt.Getopt
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
maven-jar-pluginでjarを作成するだけでは、依存するライブラリは単一のjarにまとめてくれないためです。そのため、ライブラリのクラスパス、クラス名も含めて以下のように記述する必要が出てきています。
java -jar ./target/DirectoryMerge-1.0-SNAPSHOT.jar -classpath クラスパス1;クラスパス2; クラス名1;クラス名2
ちなみに、Mac OSの場合、mavenでダウンロードされたクラスは~/.m2/repository
配下に保存されています。
~/.m2/groupID/artifactID/version/
cd ~/.m2/repository
% ls -alh
...
drwxr-xr-x 32 xxx staff 1.0K Dec 27 12:56 .
drwxr-xr-x 3 xxx staff 96B Dec 16 20:14 ..
drwxr-xr-x 3 xxx staff 96B Dec 20 16:32 commons-lang
drwxr-xr-x 4 xxx staff 128B Dec 25 21:16 commons-logging
...
単一のjarに依存ライブラリをまとめるMavenプラグイン
pom.xml
maven-assembly-plugin
, maven-dependency-plugin
の2つをプラグインに指定します。
appendAssemblyIdをtrue
にすると、作成されたjar
のファイル名にjar-with-dependencies
が追加されます。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.example.DirectoryMerge</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
実行
以下のコマンドでビルド、実行が出来ます。
% mvn clean
% mvn package
% java -jar ./target/DirectoryMerge-1.0-SNAPSHOT.jar