Java 11 JRE付きエクスポート
あんまり分かってないけど、とりあえずJRE付きでエクスポートまではできた。
Java 9以降のこと
-
Oracle Java(JDK)のリリースモデルが変わった
-
Public JRE(Oracleが無償配布してたJRE)がなくなった
-
Oracle JDKの配布が有償のみになる(Java 11以降)
これまでの実行可能Jar
- Javaランタイム(JRE)を同梱しなくても、システムにインストールされたPublic JREで実行できた
これから
- システムにJREがない
- 同様に実行できるようにするには、JREをアプリケーションに同梱する必要がある(?)
- これまでも
rt.jar
がJREの同梱された形としてあったはず
- これまでも
Jigsawモジュールシステム
Java 9以降導入されたJavaの依存関係システム。
依存関係はmodule-info.java
ファイルに記述する。
module sample.module {requires java.base; // 不要(省略可)}
実行可能Jarのエクスポート(Maven、JREなし)
Java 8まで、こんな感じだった。
Maven pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example.sample</groupId><artifactId>Sample</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>8</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target></properties><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.1.1</version><configuration><archive><manifest><addClasspath>true</addClasspath><mainClass>com.example.sample.Main</mainClass></manifest></archive></configuration></plugin></plugins></build></project>
JREの生成(手動、module-info使用)
コンパイルしたクラスファイルのディレクトリを指定
jlink --module-path './classes;JDK_DIRECTORY/jmods' --add-modules sample.module --output jre
Jarを指定
jlink --module-path './sample.jar;JDK_DIRECTORY/jmods' --add-modules sample.module --output jre
圧縮
-c 2
起動用スクリプトも生成してくれる。
--launcher mycmd=sample.module/com.example.sample.Main
OpenJDK 11.0.1 (Windows)で実行すると、dll, exe, ランチャーシェルスクリプト, bat他が生成された。OpenJDKの中身を絞って移してきてる? 複数OS想定する場合、JREはOS別に作る必要があるのか? それとも別の方法があるのか。
実行可能Jarのエクスポート(Maven、JREあり、ランチャー)
上の処理を自動化してくれるプラグインを使う。
ant-runの部分はjlink
ツールが出力ディレクトリを上書きしてくれないので、package
を実行するごとに削除させるため。手動で消すかclean
すれば不要。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example.sample</groupId><artifactId>Sample</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>11</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target></properties><build><plugins><!-- https://mvnrepository.com/artifact/org.moditect/moditect-maven-plugin --><plugin><groupId>org.moditect</groupId><artifactId>moditect-maven-plugin</artifactId><version>1.0.0.Beta2</version><executions><execution><id>create-runtime-image</id><phase>package</phase><goals><goal>create-runtime-image</goal></goals><configuration><compression>2</compression><modulePath><path>${project.build.outputDirectory}</path></modulePath><modules><module>sample.module</module></modules><launcher><name>Sample</name><module>sample.module/com.example.sample.Main</module></launcher><outputDirectory>${project.build.directory}/jlink</outputDirectory></configuration></execution></executions></plugin><!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-antrun-plugin --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><version>1.8</version><executions><execution><phase>initialize</phase><goals><goal>run</goal></goals><configuration><target><delete dir="${project.build.directory}/jlink" quiet="true" /></target></configuration></execution></executions></plugin></plugins></build></project>
ただ、この方法だとjarファイルが見当たらない。たぶんruntimeも自分のプログラムも混ざってどこかに入ってる。外部jarを混ぜずに読み込む方法もわからない。
JREの生成(手動、Jar使用)
module-info
を使わない方法(使わないでいいのかは分からないけど)。
jdeps --list-deps JARファイル
でmodule-info
のないJARの依存するモジュールリストが出力される。
このリストをもとに下のコマンドでJREを生成すれば混ざることはないはず。
jlink -c 2 -p 'JDK_DIRECTORY/jmods' -m モジュールカンマ区切りリスト --output jre
生成されたjava実行ファイルに対してjava -jar JARファイル
するスクリプトを書けば外にjarを置ける。
外部Jarライブラリをlibsディレクトリに置く、というのを次はやりたい。今まで通りクラスパスに追加して、JREだけ上の方法で生成する、実行はスクリプトから、は正解じゃない気がするので、どうすればいいのか。それから、Launch4j使いたい場合?