じゃぁ、1つで済ませましょ (1) [classファイルをパッキングする: jarツール]
2002-03-03
Javaでは、コンパイルを行うと、1つのクラスにつき1つのclassファイルができます。クラスの数が増えて、さらにパッケージを宣言したりすると、意外にファイルシステム上の木構造は大きくなります。これをそのまま持ち運ぶのは、結構面倒です。それを解決するためにJava2
SDKに付いているのが、jarというツールです。このツールを使うと、JAR(Java Archive)というフォーマットに従って、アプリケーションやアプレットを、その中で使用するクラスファイルやイメージ、サウンドなどと一緒に1つのファイルに固めて、パッキングすることができます。このjarというものについて見ていきましょう。
- jarツール
- jarファイルとManifest、クラスパス
- プログラムからjarファイルを使う
- 入れ子のJARの取り扱い
など、トピックを考えてみました。今回は、jarツールについて紹介します。
■固めてつぶして
jarツールは、IDE(統合開発環境)を使用していると、直接、目にすることは少ないかもしれませんが、jarファイルを作成するために、Java2
SDKに付属してくる標準的なツールです。jarは、固めるだけでなく、圧縮もしてくれます。zipファイルと同じ形式になっており、WinZipなどのツールで中身を見ることができます。また、実行環境に依存しますが例えばWindows環境では、jarファイルを実行するアプリケーションとして、javaコマンドが関連づけられています。これにより、jarファイルをダブルクリックすると、javaアプリケーションを起動することができます。
jarツールは、javacなどと同様にコマンドラインから使用します。コマンドは、以下のような形式になっており、optionsで動作を指示します。optionsで指定するオプションの形式は、Unixのtarコマンドを踏襲した形になっていますから、tarコマンドを使ったことのある人は、自然に使用することができるでしょう。
| jar [options] [manifest] destination
input-file [input-files] |
| |
コマンドの形式 |
jarコマンドに引数として渡されるファイルには、以下ようなものがあり、複数のファイルを書き並べたり、フォルダを指定したりできます。
- manifest: Manifestファイル
- destination: 出力ファイル(jarファイル)
- input-files: JARファイルに格納されるファイル(classファイル、イメージ、サウンドなど)、フォルダ
Manifestファイルには、それ自身が格納されるjarファイルについての情報が保持されます。jarコマンドは、作成したjarのバージョンのみを記述した、最低限のManifestを自動で作成します。それ以外に、動作上、独自に必要となるエントリを追加する場合には、テキストファイルで作成し、オプションで追加するように指示することになります。Manifestについては、次回のトピックとして取り上げる予定です。
jarコマンドの典型的な使い方は、以下のようになります。
| D:\> jar cvf MorePaste.jar MPMain.class
morepaste |
|
|
新しいjarファイルを作成する |
この例では、optionsとして"cvf"が指定されており、ファイルは先頭のMorePaste.jarが出力ファイル、それ以降が格納される入力ファイルになります。morepasteはフォルダで、このようにフォルダが指定されると、その中身がすべて入力ファイルとして扱われます。
optionsには、以下のようなものが指定できます。バージョンが上がるごとにいろいろなものが追加されてきているのですが、大体、これらを組み合わせて使用すればこと足ります。
| c |
新しいjarファイルを作成する |
| t |
jarファイルの中身の一覧を表示する |
| v |
jarファイルもしくは、jarコマンドの処理に関する付加的な情報を表示する |
| f |
処理対象となるjarファイルを指定する |
| u |
jarファイルを更新する |
| m |
Manifestファイルを指定する |
| -i |
JarIndexを作成する |
■使ってみれば
それでは、下のようなフォルダ構成で、classがカレントのフォルダになっていることにして、使い方を見ていくことにしましょう。「典型的な使い方」で例に出したのは、新しいjarファイルを作成する時のコマンドです。もう少し、細かく見てみます。
新しいjarファイルを作成する場合、コマンドは以下のように記述できます。optionsとして"cvf"を指定しています。ファイルは、この場合、最初が出力先のファイル名、それ以降が格納されるファイルやフォルダになります。
このコマンドを実行すると、処理の進行状況のログがメッセージ出力され、MorePaste.jarというファイルが作成されます。ログには、処理を行ったファイルとその圧縮率などのデータが含まれています。ログの例は、こちらです。
| D:\Dev<中略>\class> jar cvf
MorePaste.jar MPMain.class morepaste |
| |
新しいjarファイルの作成 |
optionsの"cvf"については、"c"が、新しいjarファイルの作成を指示していることを示しています。"v"はログを出力することを示しており、指定しなくてもかまいません。指定しない場合には、メッセージは表示されなくなります。"f"を指定すると、最初のファイルが処理結果の出力先ファイルとして扱われます。
"v"や"f"は、"c"とは違い、共通的に組み合わせて使用するオプションだといえます。"f"を指定しない場合、標準出力に出力されますから、コマンドプロンプトなどで、リダイレクトせずに実行してしまうと大変なことになります。
| D:\Dev<中略>\class> jar c
MPMain.class morepaste > MorePaste.jar |
| "f"を指定しない場合 |
新しいjarファイルの作成 |
作成したjarファイルの中身を表示させたい場合には、以下のようにコマンドを記述します。optionsには、"tf"を指定しています。"t"が、jarファイルの中身の表示を指示していることを示しています。"t"とともに"v"を用いると、付加的な情報を一緒に表示してくれます。"tf"のみの場合は、こちらのように出力されますが、"tvf"のようにすると、こちらのようになります。
| D:\Dev<中略>\class> jar tf
MorePaste.jar |
| |
jarファイルの中身の一覧表示 |
"f"を指定しない場合、jarコマンドは、標準入力からの入力を待つことになります。
| D:\Dev<中略>\class> jar t <
MorePaste.jar |
| "f"を指定しない場合 |
jarファイルの中身の一覧表示 |
プログラムを修正して、コンパイルし直したりした際に、既存のjarファイル内のclassファイルを更新したい場合があります。このような時には、以下のような書き方ができます。optionsには、"uf"を指定しています。"u"が、この処理が更新であることを示します。"f"により、先頭のMorePaste.jarが処理対象のjarファイルである、ということが指示されます。それ以降が、更新されるclassファイルとなります。例では、ワイルドカードを使ってみたりしています。フォルダを指定すれば、そこに含まれるファイルがすべて更新の対象になります。
| D:\Dev<中略>\class> jar uf
MorePaste.jar MPMain.class morepaste/ComboPlugin*.class |
| |
jarファイルの更新 |
独自にManifestファイルを作成していて、それを使ってManifestを更新する際には、ほかのファイルとは違った指定のしかたをする必要があります。この場合、以下のような書き方で行うことができます。
| D:\Dev<中略>\class> jar umf
Manifest.txt MorePaste.jar |
| Manifestの更新 |
jarファイルの更新 |
optionsに、"umf"を指定しています。"m"が、独自のManifestファイルを使うことを示しています。引数のファイルの中で、どれがManifestファイルで、どれが処理対象のjarファイルか、ということは、"m"と"f"の順序に依存します。例とは逆に、"fm"と指定した場合、先頭がjarファイルで、次がManifestであると解釈されます。
Java2のバージョン1.3以降では、JarIndexという機能がサポートされています。複数のjarファイルで構成されているアプリケーションやアプレットを起動する際に、JarIndexがあると、必要なファイルだけを開きます。このため、効率的にクラスをロードすることができるようになります。このJarIndexの作成は、以下のようにして行います。optionsには、"-i"を指定します。
| D:\Dev<中略>\class> jar -i
MorePaste.jar |
| |
JarIndexの作成 |
■バラバラでハラハラ
Javaでは、ソースファイルの段階では、1つのjavaファイルに複数のクラスを書くことができますが、その場合も、publicなクラスは1つだけしか定義できません。また、publicでない複数のクラスを1つのソースファイルに含めても、コンパイルするとそれぞれ独立したclassファイルになります。packageを宣言すると、それらはディレクトリ階層に対応づけられますから、ファイルシステム上の木構造は意外に大きなものになります。
可視性に関するクラス修飾子は、public以外では、修飾子なし、protected、privateしかありませんから、ディレクトリ階層上、別フォルダからアクセスできるクラスは、1つのクラスファイルにつきpublicなもの1つだけ、と整理することができます。
このように、classごとにファイルが分かれている、ということに対しては、いろいろな意見があると思いますが、ネットワークのトランザクションという点では不利に働きます。jarツールのドキュメントの中でも述べられていることですが、Appletをダウンロードする場合、classファイルごとにチマチマ通信を行うと、HTTPのトランザクションがそれごとに発生し、非効率です。jarという形で、1つのファイルにまとめれば、確実に改善につながります。
classごとにファイルを構成している利点の生かし方としては、修正した際に、更新の行われたclassだけを入れ替えたり、必要なclassファイルだけでアプリケーションを構成する、といったことが挙げられます。Java2
SDK 1.4からは、アプレット、アプリケーションに続き、第3の配布手段である、Java Web Start(JWS)が標準になります。JWSでは、キャッシュされたjarとダウンロードしたjarで、含まれるクラスごとに中身を比較する、ということを目指しているようです。(それを匂わせるjarファイルが付属して来ます。)
さて、冒頭でWindows環境では、jarファイルをダブルクリックして、アプリケーションが起動できる、ということを述べました。しかしながら、ただjarに固めただけでは、起動することはできません。これができるようにするためには、Manifestにそのための情報を記述する必要があります。次回は、Manifestの中身やjarの構造について見てみたいと思います。

|