Java パッケージガイドライン

提供: ArchWiki
ナビゲーションに移動 検索に移動

この文章では Arch Linux における Java プログラムのパッケージングについて提唱される標準を定義しています。Java プログラムは依存関係を重ねないようにパッケージ化するのが大変難しいことで有名です。この文章ではそれをなんとか改善する方法を説明します。Java アプリケーションを扱うときは様々な場面に合わせて以下のガイドラインを臨機応変に読み替えてください。

イントロダクション

Java パッケージの処理方法について Arch Linux のパッケージ作成者が合意を取ることは不可能です。公式・非公式リポジトリや AUR に存在する PKGBUILD では様々な手段が使われています。/opt に全てのファイルを配置して、/usr/bin にシェルスクリプトを置いたり /etc/profile にプロファイルを保存する方法もあれば、/usr/share のディレクトリにファイルを配置して /usr/bin にスクリプトを置いているのもあります。システムの CLASSPATHPATH には多くの不必要なファイルが追加されています。

典型的な Java アプリケーションの構造

ほとんどの Java のデスクトップアプリケーションは同じような構造をしています。これらのアプリケーションはシステムに依存しない (ただしパッケージに依存する) インストーラーによってインストールされます。大抵は全てを単一のディレクトリにインストールして bin, lib, jar, conf などのサブディレクトリが作られます。通常、メインの jar ファイルが存在していて、メインの実行クラスが記述されています。また、Java インタプリタを直接実行しなくてもいいように、メインクラスを実行するためのシェルスクリプトも付属しているのが普通です。シェルスクリプトは様々なディストリビューションで共通して用いられ、別の環境 (例: Cygwin) 用の特殊なケースもカバーするようになっている場合が多く、非常に複雑になっています。

lib ディレクトリには jar ファイルがバンドルされているのが通例で、Java アプリケーションの依存関係を満たすようになっています。(全ての依存パッケージが含まれていることは) プログラムをインストールしたいユーザーにとっては楽ですが、パッケージの開発者にとっては悪夢です。同一の依存パッケージを複数のパッケージがバンドルしていることは無駄に他なりません。Java のデスクトップアプリケーションやライブラリの数が少なかった昔はそこまで大きな問題ではありませんでしたが、Java アプリケーションとライブラリの数が増えるにつれて避けがたい問題になっています。時代は変わったのです。

プログラムを実行するのに必要な他のファイルはメインの jar ファイルと同じフォルダに保存されるか、サブディレクトリに保存されるのが普通です。Java プログラムはどこからクラスがロードされたか関知しないので、jar ファイルがあるディレクトリ内から実行しなくてはなりません (シェルスクリプトでディレクトリに cd する必要がある) あるいは、ディレクトリの場所を示す環境変数を設定します。

パッケージング

Arch で Java アプリケーションをパッケージ化するのは骨の折れる作業です。しかしながら、上手くパッケージ化することでファイルシステムをきれいにして同梱する依存ライブラリを減らせます (Java ライブラリがパッケージとして作り直されることで、パッケージ化も楽になります)。Arch Linux の Java パッケージを作成するときは以下のガイドラインに従ってください:

  • Java ライブラリの名前が普遍的なものである場合、パッケージの名前に java- を付けて他のライブラリと区別ができるようにしてください。ユニークな名前が付いているパッケージ (JUnit など) やエンドユーザープログラム (Eclipse など)、他のプリフィックスが存在するライブラリ (jakarta-commons-collections や apache-ant など) では必須ではありません。
  • Java アプリケーションをソースからコンパイルする必要はありません。gcc で作成されたバイナリと同じように、コンパイルによって得られる最適化は僅かです。ソースからビルドする簡単な方法がソースパッケージに用意されている場合はそれを使ってかまいませんが、バイナリリリースの jar ファイルやインストーラーを取得するほうが簡単な場合はそれで結構です。
  • プログラムと一緒に配布されている jar ファイルは全て /usr/share/java/myprogram ディレクトリに配置してください。アプリケーションの依存ライブラリとして配布されている jar ファイルも含みます。ただし、一般的に使われるライブラリや巨大なライブラリ群は独立した別のパッケージとするべきです。プログラムが特定のバージョンのライブラリに依存しない場合にこれが当てはまります。
このルールにより、依存関係を反復的にリファクタリングできるようになります。つまり、パッケージとそのすべての依存関係を最初に 1 つのディレクトリに配置できます。これをテストした後、主要な依存関係を一度に 1 つずつリファクタリングできます。一部のアプリケーションには、メインの jar ファイル内にバンドルされた依存関係が含まれていることに注意してください。つまり、バンドルされた依存関係を解凍し、メインの jar に含めます。このような依存関係は通常非常に小さいため、リファクタリングする意味はほとんどありません。
  • ユーザーがプログラムを実行するようになっている場合、メインの jar ファイルを起動するカスタムシェルスクリプトを書いてください。実行スクリプトは /usr/bin に配置します。ライブラリは基本的にシェルスクリプトを必要としません。プログラムに付属しているスクリプトを使うよりも、スクラッチからシェルスクリプトを書くことを推奨します。(Cygwin など) カスタム環境をテストするコードや、JAVA_HOME が設定されているかどうか確認するコードは削除してください (Arch では JAVA_HOME使用せずarchlinux-java を使って /usr/bin/java シンボリックリンクを設定します)。
jar ファイルのスクリプトは以下のようになります:
#!/bin/sh
exec /usr/bin/java -jar '/usr/share/java/PROGRAMNAME/PROGRAMNAME.jar' "$@"
クラスファイルのスクリプトは以下のようになります:
#!/bin/sh
exec /usr/bin/java '/usr/share/java/PROGRAMNAME/PROGRAMCLASSNAME' "$@"
  • 明示的な理由がない限り、-cp オプションを使用して CLASSPATH を Java インタープリタに設定します (つまり、CLASSPATH はプラグイン メカニズムとして使用されます) )CLASSPATH には、/usr/share/java/myprogram ディレクトリ内のすべての jar ファイルに加えて、他のディレクトリにリファクタリングされた依存関係ライブラリの jar ファイルも含める必要があります。次のコードのようなものを使用できます。
for name in /usr/share/java/myprogram/*.jar ; do
  CP=$CP:$name
done
CP=$CP:/usr/share/java/dep1/dep1.jar
java -cp $CP myprogram.java.MainClass
  • シェルスクリプトが実行可能であることを確認してください。
  • パッケージとともに配布されるその他のファイルは、/usr/share の下のパッケージにちなんで名付けられたディレクトリに保存する必要があります。シェル スクリプト内の MYPROJECT_HOME のような変数にこのディレクトリの場所を設定する必要がある場合があります。このガイドラインは、プログラムがすべてのファイルが同じディレクトリにあることを期待していることを前提としています (Java パッケージの標準と同様) 設定ファイルを別の場所に置いたほうが自然だと思われる場合 (たとえば、ログを /var/log に置くなど)、してください。
環境によっては /usr は読み取り専用でマウントされる場合もあるので注意してください。アプリケーションによる書き込みが必要なファイルが共有ディレクトリに存在する場合、/etc/var、あるいはユーザーのホームディレクトリに再配置できないか確認してください。
  • Arch Linux パッケージの標準と同様、多大な労力を費やすことなく上記の標準に従うことができない場合は、パッケージを適切な方法でインストールし、その結果ディレクトリが /opt に配置されるようにする必要があります。これは、JRE をバンドルするプログラム、依存関係のカスタマイズされたバージョンを含めるプログラム、またはその他の奇妙なタスクや面倒なタスクを実行するプログラムに役立ちます。

複数の API 実装

一般的に使われる API 実装 (JDBC ドライバーなど) を配布するパッケージは /usr/share/java/apiname にライブラリを配置してください。アプリケーションからユーザーが実装を選択できるようにするためです。/usr/share/java/apiname を使用できるのはライブラリしか含まないパッケージだけです。アプリケーションの一部として実装が含まれる場合、通常のパッケージツリーと同じ場所に配置してください。

ディレクトリ構造の例

以下は foo という仮のプログラムのディレクトリ構造の例です。foo は一般的な名前なので、パッケージの名前は java-foo としていますが、以下のディレクトリではその名前は使っていません:

  • /usr/share/java/foo/
  • /usr/share/java/foo/foo.jar
  • /usr/share/java/foo/bar.jar (java-foo の依存ライブラリ)
  • /usr/share/foo/
  • /usr/share/foo/*.* (java-foo が必要とする汎用のファイル)
  • /usr/bin/foo (実行可能なシェルスクリプト)

依存パッケージ

Java パッケージは、必要に応じて、依存関係として java-runtime または java-environment を指定する場合があります。

ほとんどのパッケージでは、Java で書かれたソフトウェアを単純に実行するために必要なものは java-runtime です。

java-environment (JDK など) は、Java ソースコードをバイトコードにコンパイルする必要があるパッケージに必要です。

詳細については、Java を参照してください。