javaでライブラリとかをまとめるFatJar(実行可能jar)は、Javaを知らない人に渡すときに便利。
でも、いろいろとはまったので、その備忘録。
ハマりまくって、学んだことは、2つ。
- 実行可能jarのクラスパスは、実行時に指定できない
- jar内の
META-INF/MANIFEST.MF
に設定があるため。
- jar内の
- 実行可能jarを直接実行すると、標準出力が表示されない
$ ./xxxx.jar
を実行すると、$ javaw -jar xxxx.jar
として実行されるため。
コンパイラのJavaバージョンを指定
<project> <properties> <!-- 文字コードの指定 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- コンパイルするJavaのバージョンを指定。デフォルトだと1.5になるのでハマる --> <java.version>1.8</java.version> <maven.compiler.target>${java.version}</maven.compiler.target> <maven.compiler.source>${java.version}</maven.compiler.source> </properties> </project>
clean時にローカルのjarをインストールする設定
そんなときは、Apache Maven Install Pluginを使う。
<project> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> <executions> <execution> <id>install-external</id> <phase>clean</phase> <configuration> <file>${project.basedir}/src/main/resources/mylib-1.0.0.jar</file> <repositoryLayout>default</repositoryLayout> <groupId>jp.my.libs</groupId> <artifactId>mylib</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <generatePom>true</generatePom> </configuration> <goals> <goal>install-file</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
package時にFatJarを作る設定
<project> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>MyMain</mainClass> </manifest> <manifestEntries> <!-- クラスパスの設定はここでする!!。 起動オプションでは有効にならない。 --> <Class-Path>./</Class-Path> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build> </project>
ここが最大のハマリポイントだった。。
プロパティファイルをローカルに配置して読み込むが、読み込まれず。。。
クラスパスを見ても、カレントディレクトリが含まれておらず。。。
jarの中に同梱されるMETA-INF/MANIFEST.MF
を変更しないといけないらしい。。
ちなみに、実行しているjarの、クラスパスの確認方法は以下な感じ。(つさんの記事から引用)
System.out.println("classpath : " + System.getProperty("java.class.path"));
とりあえず、<manifestEntries><Class-Path>./</Class-Path></manifestEntries>
を追加して、読み込めるようになったが、
実行してみると別の問題が。。。
jarを直接実行すると、標準出力が表示されない
$ java -jar xxxx.jar
で実行すると表示されるが、$ ./xxxx.jar
とすると表示されないよう。。
この記事をみると以下のように書いてある。
ただし これは「javaw -jar hello.jar」が裏で実行されているだけ。
すなわち(javaでなくjavawだから)ウィンドウが開かないので、System.out.println()等でコンソール入出力をしているプログラムは何も表示されない。
おぉぉ。とりあえず、jreをインストールしてもらう or 同梱して配布するか。。。
以上!!
参考にしたサイト様
- mavenのコンパイルjavaバージョンを指定する - Qiita
- Maven Assembly Plugin で外部依存 jar をまとめる - A Memorandum
- java - Java アプリケーション起動コマンド
- Apache Maven Archiver – Manifest Entries
- Mavenリポジトリにないライブラリをpom.xmlで指定する方法 - システム開発メモ
- java - How to add local jar files in maven project? - Stack Overflow
- Mavenでfat jarを生成する - 覚えたら書く
- JAR ファイルの仕様
- Jarファイルメモ(Hishidama's java-archive Memo)
- Apache Maven Archiver – Manifest Entries
- MANIFEST.MFとjarファイル - 役立たずのプログラマーブログ
- javaのクラスパスを取得|IT忘備録・メモ書きと日記