【Java】JARファイルの作成方法

Java

JARファイルの作成について

JARファイルとは、拡張子が .jar になっているだけのZIP形式のアーカイブファイルです。従ってJARファイルを作成したければ、クラスファイルを(パッケージに合わせたディレクトリ構成で)ZIPファイルにまとめ、拡張子を .zip から .jar に書き換えるだけで済みます。

この点についてはこちらでも詳細を説明しています。

しかし通常は併せてマニフェストファイルも同梱することが推奨されます。これもまた決められたディレクトリに手動で配置することが可能ですが、書式が厳格なためツールを利用する方が簡単です。ここでは 手動で作成する方法 の他、jarコマンドMavenを使用 して作成する方法を挙げています。

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.MF
Manifest-Version: 1
Created-By: Manual

マニフェストファイルは単なるテキストファイルであるため簡単に自作できますが、:の後に半角スペースを空ける、改行で終了する等(名前と値のペアおよびセクション)、書式に厳格なため手動作成する場合は注意が必要です。

実行可能JARファイルの作成

実行可能JARファイルを作成する場合は、マニフェストファイルにMain-Class属性を追加します。

MANIFEST.MF
Main-Class: com.example.Main

これにより、-cpオプションによるクラスパス追加でなく、-jarオプションで直接JARファイルを指定して指定して実行することができるようになります。

# 実行可能JARファイルのため -jar オプションで実行可能
> java -jar app.jar
Person01 has been created!

前述 の通りマニフェストファイルを手動作成して配置する場合は、書式に誤りが無いか注意が必要になります。少しでも間違いがあると正しく実行することができません。

悪い例):の後に半角スペースが無い場合

MANIFEST.MF
Main-Class:com.example.Main

> java -jar app.jar
Error: Invalid or corrupt jarfile app.jar

悪い例)改行で終了していない場合

MANIFEST.MF
Main-Class: com.example.Main
> java -jar app.jar
app.jarにメイン・マニフェスト属性がありません

jarコマンドを使う場合

jarコマンドを使うことで、手動で作成する場合の手順を踏むことなく、対象ディレクトリとアーカイブファイル名を指定するだけで、JARファイルを作成することが可能です。また、併せてマニフェストファイルも正しいディレクトリに正しい形式で自動生成されるため、書式の不備による不具合を防ぐことができます。

jarコマンドはJDKに同梱されているツールのため、javaコマンドが使用できる環境であれば追加でツールをインストールする必要がないという利点もあります。

前述 のサンプルを例に、jarコマンドでJARファイルを作成する方法を確認します。新規作成する場合の基本構文は次の通りです。(-cオプション

# -c:アーカイブ作成(Create)
# -v:詳細情報を出力(Verbose)
# -f:ファイル名指定(File)
> jar -cvf <JARファイル名> <対象のディレクトリパス>

comディレクトリをJARファイルに格納したい場合は、第二引数に対象のディレクトリパスとして指定します。-vオプションにより詳細情報が出力されるため、正しくディレクトリの指定ができているか確認することも可能です。

# カレントディレクトリに 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.MF
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コマンドを実行する必要があります。そこで、この操作を行うためのオプションが用意されています。-Cオプション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コマンド の二つを使用しました。javaはJARファイルをクラスパスに追加したり実行可能JARファイルを-jarオプションに指定したりしてJavaプログラムを起動するための実行用ツール、jarはJARファイルを作成したり展開したりするための開発用ツール、という違いがあります。これはjavaコマンドがJREに含まれ、jarコマンドがJDKに含まれていることからも分かります。( JDK・JRE とは

tarコマンドとの比較

jarコマンドで使用することのできるオプションは、Linuxでしばしば利用されるアーカイブ形式のTARファイル(Tape ARchive)用の tarコマンド と、その多くが共通しています。そのためtarコマンドについて馴染みがあれば分かりやすいかもしれません。

例えばJARファイルの中身を確認する際、これまでの手順では一度拡張子を.zipに書き換えてから展開していましたが、jarコマンドにはtarコマンドと同じく-tオプションや-xオプションが用意されています。

目次用の -tオプション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

抽出用の -xオプション(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コマンドオプション機能
-c, --create-c, --create作成(create)
-t, --list-t, --list一覧表示・目次(table of contents)
-x, --extract-x, --extract展開・解凍・抽出(extract)
-f, --file-f, --fileファイル名指定(file)
-v, --verbose-v, --verbose詳細出力(verbose)
-C-Cディレクトリ切替(Change Directory)

TARファイルの場合、これは単なるアーカイブファイルであるため、圧縮も行いたい場合はgzipコマンド-zオプション(あるいは他の圧縮形式)を併せて使用します。JARファイルも同様に、あくまで圧縮はオプション機能の位置づけであるZIPファイル形式ですが、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コマンドでは、実行可能JARファイルの作成も容易です。-eオプションを使用してエントリポイント(entry point)となるクラスを指定することで、MANIFEST.MFMain-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.MF
Manifest-Version: 1.0
Created-By: 25.0.2 (Oracle Corporation)
Main-Class: com.example.Main

Mavenを使う場合

jarコマンドを利用 することで、様々なオプションを指定して任意のJARファイルを作成することができました。さらにMavenを使えば、これらオプション設定を全てpom.xmlに記述しておくことで、より簡単に同じ構成でJARファイルを作成することができます。

まずは Creating a Project に沿い Maven Archetype を使ってテンプレートを基にMavenプロジェクトを生成する等、Mavenの 標準ディレクトリ構成 でJavaのソースファイルを準備します。あるいは Spring Initializr 等でも、Mavenを選択すればこのディレクトリ構成でプロジェクトを初期化することが可能です。

あとは > mvn package コマンドを実行するだけで、JARファイルが作成され、targetディレクトリに出力されます。これはMavenのパッケージングがデフォルトで jar になっているためです。( Packaging

ここでは説明の簡略化のため、手動で標準ディレクトリ構成を準備します。初めに先程comディレクトリを src/main/java ディレクトリ下に配置します。

> tree
・・・
└─src
    └─main
        └─java
            └─com
                └─example
                    ├─model
                    └─service

続いてディレクトリ直下に POM を配置します。ここでは次のような最小構成のpom.xmlを作成して配置します。

pom.xml
<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フェーズを指定することで、validatecompiletestpackageが順に実行され、pom.xmlに定義した通りのapp.1.0.0.jartargetディレクトリに作成されます。

# 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.MF
Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.4.1
Build-Jdk-Spec: 25

これは Maven JAR Plugin が Maven Archiver 設定に基づいてJARファイルを作成しており、そのデフォルトが Default Manifest の3属性となっているためです。

実行可能JARファイルの作成

Main-Class属性を追加して 実行可能JARファイル を作成したい場合、pom.xmlMaven JAR Plugin による Maven Archiver 設定を追記します。(例:Make The Jar Executable

前述 の最小構成POMを使用する場合、次のように <mainClass> 設定を追加します。

pom.xml
<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.MF
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 に変更
    • マニフェストファイル:テキストファイルを自作(/META-INF/MANIFEST.MF
    • 実行可能JARファイル:マニフェストにMain-Class属性を記述
  • jarコマンドを使う場合
    • -c, --create オプション( および -f )で作成
    • マニフェストファイル:デフォルトで自動生成される
    • 実行可能JARファイル:-e, --main-class オプションを使用
  • Mavenを使う場合
    • mvn package で作成
    • マニフェストファイル:デフォルトで自動生成される
    • 実行可能JARファイル:pom.xml<mainClass> を追加