Java JMODファイルとは、JARファイルとの違い。

この記事では、JPMS (Java Platform Module System) が導入されてから追加された、
新しいファイル形式、JMODファイルについて解説します。
また、元々あるJARファイルとの違いについても触れていきます。

最後に、JMODファイルの作成方法を通して、
JMODファイルが、実際どういうものなのか、更に理解を深めたいと思います。

JMODファイルとは

JMODファイルは、Java9から追加された、
モジュールという単位で、
クラスファイルとネイティブコードなどをZipアーカイブしたファイルです。

JMODファイルは、Javaのコンパイル、リンク時に利用する為のファイルです。
JARのように、ランタイム時に参照して実行するようなことはできません。

実行時に使おうとすると、下記の例外が発生します。

java.lang.module.ResolutionException

あくまでビルド時に使うもの。
特に JIMAGE (カスタムRuntime) を生成するのを目的に利用します。

ネイティブコードを含んでいることが多い為、
Windows, Linux, MacOS のような各プラットフォームごとに
JMODファイルは提供されます。

Java自体もJMODで提供されている

Java9以降では、Java自体もモジュール化されており、
JDKに、jmodファイルが提供されています。

場所は、jmodsというディレクトリ配下に、ずらっと置かれています。

$ ls $JAVA_HOME/jmods
java.base.jmod                           java.sql.rowset.jmod                     jdk.internal.opt.jmod                    jdk.management.jfr.jmod
java.compiler.jmod                       java.transaction.xa.jmod                 jdk.internal.vm.ci.jmod                  jdk.management.jmod
java.datatransfer.jmod                   java.xml.crypto.jmod                     jdk.internal.vm.compiler.jmod            jdk.naming.dns.jmod
java.desktop.jmod                        java.xml.jmod                            jdk.internal.vm.compiler.management.jmod jdk.naming.rmi.jmod
java.instrument.jmod                     jdk.accessibility.jmod                   jdk.jartool.jmod                         jdk.net.jmod
java.logging.jmod                        jdk.aot.jmod                             jdk.javadoc.jmod                         jdk.pack.jmod
java.management.jmod                     jdk.attach.jmod                          jdk.jcmd.jmod                            jdk.rmic.jmod
java.management.rmi.jmod                 jdk.charsets.jmod                        jdk.jconsole.jmod                        jdk.scripting.nashorn.jmod
java.naming.jmod                         jdk.compiler.jmod                        jdk.jdeps.jmod                           jdk.scripting.nashorn.shell.jmod
java.net.http.jmod                       jdk.crypto.cryptoki.jmod                 jdk.jdi.jmod                             jdk.sctp.jmod
java.prefs.jmod                          jdk.crypto.ec.jmod                       jdk.jdwp.agent.jmod                      jdk.security.auth.jmod
java.rmi.jmod                            jdk.dynalink.jmod                        jdk.jfr.jmod                             jdk.security.jgss.jmod
java.scripting.jmod                      jdk.editpad.jmod                         jdk.jlink.jmod                           jdk.unsupported.desktop.jmod
java.se.jmod                             jdk.hotspot.agent.jmod                   jdk.jshell.jmod                          jdk.unsupported.jmod
java.security.jgss.jmod                  jdk.httpserver.jmod                      jdk.jsobject.jmod                        jdk.xml.dom.jmod
java.security.sasl.jmod                  jdk.internal.ed.jmod                     jdk.jstatd.jmod                          jdk.zipfs.jmod
java.smartcardio.jmod                    jdk.internal.jvmstat.jmod                jdk.localedata.jmod
java.sql.jmod                            jdk.internal.le.jmod                     jdk.management.agent.jmod

これらのJMODファイルには、
提供プラットフォーム用にネイティブコードなどが含まれている。

JARファイルとは

JARファイルについても、おさらいしておきましょう。
JARファイルは昔からあるファイル形式です。

Javaコードをコンパイルして
生成されたclassファイル、リソースファイルをZipアーカイブしたファイルです。
マニフェストファイルなども含む。

JARファイルは、javacコマンドのクラスPATHに指定して、
ライブラリとしてコンパイル時にも利用できますし、
ラインタイムに指定して実行時に利用することも可能。

JMODファイルと、JARファイルの違い。

  • JMODファイルはコンパイル、リンク用のライブラリファイル。
    特に、jlinkコマンドを使って、カスタムランタイムイメージを生成するのに利用します。
    JMODファイルには、ネイティブコードが含まれているので、
    各プラットフォーム向けに、クロスコンパイルが可能になる。

  • JARファイルは、コンパイル時のライブラリファイルとして、
    更に、ランタイムにクラスPATH指定して実行ファイルとしても利用できるファイルです。
    JARファイルの方が、両方できるので便利でがありますが、
    ネイティブコードを含めることはできません。

JARとJMODが内包するファイルの違い

jmodコマンド

JMODファイルの作成や、
中身の確認には、jmodコマンドを使用します。

jmod create

JMODファイルの作成
モジュール化したJARファイルや、ネイティブコードを指定して .jmodファイルを生成する。

jmod list

JMODファイルの内容物を一覧で取得できます。
Zip解凍して、ファイル一覧を見る事もできますが、
一覧みたいだけなら、このコマンドで充分。

jmod describe

module-info.java に記載した内容の確認。
requires, exports, transitive など
どのようにモジュール定義しているのかを確認することができます。

JMODファイルの作り方

JMODファイルを実際につくってみましょう。
モジュール化したJARファイルは用意しておきます。
(module-info.java が含まれる)

jmodコマンドを使って、JMODファイルを作成します。

# 出力用のディレクトリ用意 
# (どこでもよい)
mkdir -p out/jmods

# jmodファイルの作成 
# (モジュール化したJARファイルを指定するだけ)
jmod create \
    --class-path build/libs/sample-1.0-SNAPSHOT.jar \
    out/jmods/net.tyablog.sample.jmod

JARファイルを指定して、
出力ファイル名(拡張子 .jmod)を指定するだけで出来上がります。

ファイル名は好きな名称にできますが、
モジュール名と同じにしておくのが間違いないでしょう。

JMODファイルを解凍してみる。

JMODファイルの実態は、Zipファイルです。
unzipコマンドなどで解凍してみると、
このJMODファイルの中身はこんな感じになっている事がわかります。

classes
├── META-INF
│   └── MANIFEST.MF
├── module-info.class
└── net
    └── tyablog
        └── sample
            └── Sample.class

classesというディレクトリに、
JARファイルの内容物が入っているだけですね。

java.desktop.jmodを解凍してみる。

次は、java.desktop.jmodという
JDKについてくる、Java自体のモジュールファイルの中身を見てみましょう。

こちらもunzipコマンドで解凍するとこんな感じ。

$ tree -L 3 .
.
├── classes
│   ├── apple
│   │   └── laf
│   ├── com
│   │   ├── apple
│   │   └── sun
│   ├── java
│   │   ├── applet
│   │   ├── awt
│   │   └── beans
│   ├── javax
│   │   ├── accessibility
│   │   ├── imageio
│   │   ├── print
│   │   ├── sound
│   │   └── swing
│   ├── module-info.class
│   └── sun
│       ├── applet
│       ├── awt
│       ├── font
│       ├── java2d
│       ├── lwawt
│       ├── print
│       └── swing
├── conf
│   └── sound.properties
├── include
│   ├── darwin
│   │   └── jawt_md.h
│   └── jawt.h
├── legal
│   ├── ADDITIONAL_LICENSE_INFO
│   ├── ASSEMBLY_EXCEPTION
│   ├── LICENSE
│   ├── colorimaging.md
│   ├── freetype.md
│   ├── giflib.md
│   ├── harfbuzz.md
│   ├── jpeg.md
│   ├── lcms.md
│   ├── libpng.md
│   ├── mesa3d.md
│   ├── opengl.md
│   └── xwindows.md
└── lib
    ├── fontconfig.bfc
    ├── fontconfig.properties.src
    ├── libawt.dylib
    ├── libawt_lwawt.dylib
    ├── libfontmanager.dylib
    ├── libfreetype.dylib
    ├── libjavajpeg.dylib
    ├── libjawt.dylib
    ├── libjsound.dylib
    ├── liblcms.dylib
    ├── libmlib_image.dylib
    ├── libosx.dylib
    ├── libosxapp.dylib
    ├── libosxui.dylib
    ├── libsplashscreen.dylib
    ├── psfont.properties.ja
    └── psfontj2d.properties

classesの他に、conf, include, libなどが含まれています。
MacOS用のJDKのため、.dylibなどMac用のネイティブライブラリが含まれているのがわかりますね。

 まとめ

  • Java9から、あたらくJMODファイルというのが追加された。
    カスタムランタイムを生成するなど、ビルド時に利用するためのファイル。

  • JARファイルのように、ランタイムに指定して実行できるわけではない。
    あくまでビルド時専用のファイル

  • ネイティブコードを含んでいるため、
    JMODファイルだけあれば、各プラットフォーム向けにクロスコンパイルすることも可能。

  • 実態は、Zipアーカイブなので、解凍して中身を見ることも可能ですが、
    jmod listjmod describeで確認ができる。

コメントを残す