JARファイルの作成について
JARファイルとは、拡張子が .jar になっているだけのZIP形式のアーカイブファイルです。従ってJARファイルを作成したければ、クラスファイルを(で)ZIPファイルにまとめ、拡張子を .zip から .jar に書き換えるだけで済みます。
しかし通常は併せても同梱することが推奨されます。これもまた決められたディレクトリに手動で配置することが可能ですが、書式が厳格なためツールを利用する方が簡単です。ここでは の他、 や して作成する方法を挙げています。
JARファイルの作成手順
手動で作成する場合
例えばのサンプルプログラムを使う場合、まず次のようなZIPファイルを作成し、続いて拡張子を .jar に書き換えます。
app.zip
└ com
└ example
├ Main.class
├ model
│ └ Person.class
└ service
└ PersonService.class
ファイル名を app.zip から app.jar にすれば、手動でのJARファイル作成は完了です。次の通りjavaコマンドでプログラムを実行することができます。
# JARファイルをクラスパスに追加してプログラムを実行
> java -cp app.jar com.example.Main
Person01 has been created!
でも説明している通り、クラスパスにはZIPファイルを指定することもできるため、拡張子を書き換えず app.zip のままでも実行は可能です。
# ZIPファイルをクラスパスに追加してプログラムを実行
> java -cp app.zip com.example.Main
Person01 has been created!
を追加したい場合は、先程のZIPファイルにMETA-INFディレクトリとMANIFEST.MFファイルを追加します。
app.zip
├ META-INF
│ └ MANIFEST.MF
└ com
└ example
├ Main.class
├ model
│ └ Person.class
└ service
└ PersonService.class
マニフェストファイルには、例えば次のようにバージョン情報などを含めます。
Manifest-Version: 1
Created-By: Manual
マニフェストファイルは単なるテキストファイルであるため簡単に自作できますが、:の後に半角スペースを空ける、改行で終了する等()、書式に厳格なため手動作成する場合は注意が必要です。
実行可能JARファイルの作成
を作成する場合は、マニフェストファイルにMain-Class属性を追加します。
Main-Class: com.example.Main
これにより、-cpオプションによるクラスパス追加でなく、-jarオプションで直接JARファイルを指定して指定して実行することができるようになります。
# 実行可能JARファイルのため -jar オプションで実行可能
> java -jar app.jar
Person01 has been created!
の通りマニフェストファイルを手動作成して配置する場合は、書式に誤りが無いか注意が必要になります。少しでも間違いがあると正しく実行することができません。
悪い例):の後に半角スペースが無い場合
Main-Class:com.example.Main
> java -jar app.jar
Error: Invalid or corrupt jarfile app.jar
悪い例)改行で終了していない場合
Main-Class: com.example.Main
> java -jar app.jar
app.jarにメイン・マニフェスト属性がありません
jarコマンドを使う場合
を使うことで、手動で作成する場合の手順を踏むことなく、対象ディレクトリとアーカイブファイル名を指定するだけで、JARファイルを作成することが可能です。また、併せてマニフェストファイルも正しいディレクトリに正しい形式で自動生成されるため、書式の不備による不具合を防ぐことができます。
jarコマンドはに同梱されているツールのため、javaコマンドが使用できる環境であれば追加でツールをインストールする必要がないという利点もあります。
のサンプルを例に、jarコマンドでJARファイルを作成する方法を確認します。新規作成する場合の基本構文は次の通りです。()
# -c:アーカイブ作成(Create)
# -v:詳細情報を出力(Verbose)
# -f:ファイル名指定(File)
> jar -cvf <JARファイル名> <対象のディレクトリパス>
comディレクトリをJARファイルに格納したい場合は、第二引数に対象のディレクトリパスとして指定します。により詳細情報が出力されるため、正しくディレクトリの指定ができているか確認することも可能です。
# カレントディレクトリに app.jar が作成される
> jar -cvf app.jar com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
# JARファイルをクラスパスに追加してプログラムを実行
> java -cp app.jar com.example.Main
Person01 has been created!
作成されたJARファイルの拡張子を .zip に書き換えて展開し中身を見てみると、次のような内容のがデフォルトで作成されていることを確認できます。
Manifest-Version: 1.0
Created-By: 25.0.2 (Oracle Corporation)
上記の例では、jarコマンド実行時のカレントディレクトリに対象のcomディレクトリが存在していました。
# treeコマンドでカレントディレクトリ下の構成を確認
> tree
・・・
└─com
└─example
├─model
└─service
# 引数に直下のcomディレクトリを指定することでこれを起点とするapp.jarを作成可能
> jar -cvf app.jar com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
しかし次のように別の階層にあるディレクトリを使おうとすると、引数に正しいパスを指定してもJARファイルにはカレントディレクトリ下を起点として格納されてしまいます。
# 対象のcomディレクトリはカレントディレクトリ下のbin配下に存在している
> tree
・・・
└─bin
└─com
└─example
├─model
└─service
# 引数に bin/com を指定してもapp.jarにはbinを起点として格納されてしまう
> jar -cvf app.jar bin/com
マニフェストが追加されました
bin/com/を追加中です(入=0)(出=0)(0%格納されました)
bin/com/example/を追加中です(入=0)(出=0)(0%格納されました)
bin/com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
bin/com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
bin/com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
bin/com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
bin/com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
# 完全修飾クラス名com.example.Mainに対し
# app.jarの中身はbin/com/example/Main.classになっているためエラー
> java -cp app.jar com.example.Main
エラー: メイン・クラスcom.example.Mainを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: com.example.Main
そのため、cdコマンドで対象ディレクトリがある場所(ここではcomがあるbin)まで移動してからjarコマンドを実行する必要があります。そこで、この操作を行うためのオプションが用意されています。(Change Directory)で移動先のディレクトリを指定することにより、カレントディレクトリに対象ディレクトリがない場合でも適切にJARファイルを作成することが可能です。
# 対象のcomディレクトリはカレントディレクトリ下のbin配下に存在している
> tree
・・・
└─bin
└─com
└─example
├─model
└─service
# -Cオプションでディレクトリをbinに変更してからcomディレクトリを指定する
> jar -cvf app.jar -C bin com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
# 実行時のディレクトリを変更するだけのため
# -Cオプションを使用してもカレントディレクトリは変わらない
> dir /b
app.jar
bin
# app.jarの中身が正しくcom/example/Main.classになっているため実行可能
> java -cp app.jar com.example.Main
Person01 has been created!
上記の例では と の二つを使用しました。javaはJARファイルをクラスパスに追加したり実行可能JARファイルを-jarオプションに指定したりしてJavaプログラムを起動するための実行用ツール、jarはJARファイルを作成したり展開したりするための開発用ツール、という違いがあります。これはjavaコマンドがJREに含まれ、jarコマンドがJDKに含まれていることからも分かります。( )
tarコマンドとの比較
jarコマンドで使用することのできるオプションは、Linuxでしばしば利用されるアーカイブ形式のTARファイル(Tape ARchive)用の と、その多くが共通しています。そのためtarコマンドについて馴染みがあれば分かりやすいかもしれません。
例えばJARファイルの中身を確認する際、これまでの手順では一度拡張子を.zipに書き換えてから展開していましたが、jarコマンドにはtarコマンドと同じく-tオプションや-xオプションが用意されています。
目次用の (table of contents)を使用すれば、アーカイブを展開することなく中身のファイル一覧を確認することができます。
> jar -tf app.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/Main.class
com/example/model/
com/example/model/Person.class
com/example/service/
com/example/service/PersonService.class
抽出用の (extract)を使用すれば、JARファイルを直接指定して展開することができます。
> jar -xvf app.jar
ディレクトリに抽出しています: C:\Users\xxx\workspace
META-INF/が作成されました
META-INF/MANIFEST.MFが展開されました
com/が作成されました
com/example/が作成されました
com/example/Main.classが展開されました
com/example/model/が作成されました
com/example/model/Person.classが展開されました
com/example/service/が作成されました
com/example/service/PersonService.classが展開されました
jarコマンド | tarコマンド | オプション機能 |
|---|---|---|
| , | , | 作成(create) |
| , | , | 一覧表示・目次(table of contents) |
| , | , | 展開・解凍・抽出(extract) |
| , | , | ファイル名指定(file) |
| , | , | 詳細出力(verbose) |
| ディレクトリ切替(Change Directory) |
TARファイルの場合、これは単なるであるため、圧縮も行いたい場合はや(あるいは他の圧縮形式)を併せて使用します。JARファイルも同様に、あくまで圧縮はオプション機能の位置づけであるですが、jarコマンドではアーカイブの際、tarコマンドと異なりデフォルトで圧縮も行われます。
# デフォルトでは圧縮も行われる(~%収縮されました)
> jar -cvf app.jar com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
# -0(--no-compress)を使用することで圧縮をせずアーカイブのみにできる
> jar -c0vf app.jar com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=1007)(0%格納されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=365)(0%格納されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=395)(0%格納されました)
実行可能JARファイルの作成
マニフェストファイルが自動生成されるjarコマンドでは、の作成も容易です。を使用してエントリポイント(entry point)となるクラスを指定することで、MANIFEST.MFにMain-Class属性が追加されます。
# -eオプションでcom.example.Mainを指定することで
# マニフェストファイルに「Main-Class: com.example.Main」が追加される
> jar -cvef com.example.Main app.jar -C bin com
マニフェストが追加されました
com/を追加中です(入=0)(出=0)(0%格納されました)
com/example/を追加中です(入=0)(出=0)(0%格納されました)
com/example/Main.classを追加中です(入=1007)(出=548)(45%収縮されました)
com/example/model/を追加中です(入=0)(出=0)(0%格納されました)
com/example/model/Person.classを追加中です(入=365)(出=258)(29%収縮されました)
com/example/service/を追加中です(入=0)(出=0)(0%格納されました)
com/example/service/PersonService.classを追加中です(入=395)(出=266)(32%収縮されました)
# 実行可能JARが作成されるため-jarオプションで実行可能
> java -jar app.jar
Person01 has been created!
の-xオプションで展開(> jar -xvf app.jar)してみると、次の通りマニフェストファイルに com.example.Main が追加されていることを確認できます。
Manifest-Version: 1.0
Created-By: 25.0.2 (Oracle Corporation)
Main-Class: com.example.Main
Mavenを使う場合
することで、様々なオプションを指定して任意のJARファイルを作成することができました。さらにMavenを使えば、これらオプション設定を全てpom.xmlに記述しておくことで、より簡単に同じ構成でJARファイルを作成することができます。
まずは に沿い を使ってテンプレートを基にMavenプロジェクトを生成する等、Mavenの でJavaのソースファイルを準備します。あるいは 等でも、Mavenを選択すればこのディレクトリ構成でプロジェクトを初期化することが可能です。
あとは > mvn package コマンドを実行するだけで、JARファイルが作成され、targetディレクトリに出力されます。これはMavenのパッケージングがデフォルトで jar になっているためです。( )
ここでは説明の簡略化のため、手動で標準ディレクトリ構成を準備します。初めに のcomディレクトリを src/main/java ディレクトリ下に配置します。
> tree
・・・
└─src
└─main
└─java
└─com
└─example
├─model
└─service
続いてディレクトリ直下に を配置します。ここでは次のようなを作成して配置します。
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>app</artifactId>
<version>1.0.0</version>
</project>
この状態での内、defaultライフサイクルのpackageフェーズを指定することで、validate→compile→test→packageが順に実行され、pom.xmlに定義した通りのapp.1.0.0.jarがに作成されます。
# Mavenの標準ディレクトリ構成でsrcとpom.xmlを用意
> tree /f
・・・
│ pom.xml
│
└─src
└─main
└─java
└─com
└─example
│ Main.java
│
├─model
│ Person.java
│
└─service
PersonService.java
# packageフェーズを指定してJARファイルを作成
> mvn package
・・・
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
・・・
# targetディレクトリに作成されたJARファイルをクラスパスに追加してプログラムを実行
> java -cp target\app-1.0.0.jar com.example.Main
Person01 has been created!
Mavenの場合、デフォルトでは次のようなが作成されます。
Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.4.1
Build-Jdk-Spec: 25
これは Maven JAR Plugin が Maven Archiver 設定に基づいてJARファイルを作成しており、そのデフォルトが の3属性となっているためです。
実行可能JARファイルの作成
Main-Class属性を追加して を作成したい場合、pom.xml に による 設定を追記します。(例:)
の最小構成POMを使用する場合、次のように <mainClass> 設定を追加します。
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>app</artifactId>
<version>1.0.0</version>
<!-- 最小構成のPOMに以下を追加 -->
<build>
<plugins>
<!--
| Maven JAR Plugin による Maven Archiver 設定を行い
| マニフェストファイルにMain-Class属性が追加されるよう構成する
-->
<plugin>
<!-- Maven JAR Plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<!-- Maven Archiver 構成 -->
<configuration>
<archive>
<manifest>
<!-- Main-Class: com.example.Main -->
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
これにより、> mvn package でJARファイルを作成すると、次のようにMain-Class属性が追加されたマニフェストファイルが生成され、実行可能JARとして-jarオプションで起動できるようになります。
Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.4.1
Build-Jdk-Spec: 25
Main-Class: com.example.Main
# packageフェーズを指定して実行可能JARファイルを作成
> mvn package
・・・
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
・・・
# targetディレクトリに実行可能JARが作成されるため-jarオプションで実行可能
> java -jar target\app-1.0.0.jar
Person01 has been created!
JARファイル作成の要点
- JARファイルの作成方法
- ZIPファイルの拡張子を
.zipから.jarに変更( )
- ZIPファイルの拡張子を
- 手動で作成する場合
- ZIPファイルの拡張子を
.zipから.jarに変更 - マニフェストファイル:テキストファイルを自作(
/META-INF/MANIFEST.MF) - 実行可能JARファイル:マニフェストに
Main-Class属性を記述
- ZIPファイルの拡張子を
- jarコマンドを使う場合
-c,--createオプション( および-f)で作成- マニフェストファイル:デフォルトで自動生成される
- 実行可能JARファイル:
-e,--main-classオプションを使用
- Mavenを使う場合
mvn packageで作成- マニフェストファイル:デフォルトで自動生成される
- 実行可能JARファイル:
pom.xmlに<mainClass>を追加


