4

これは二部構成の質問だと思います。MyFirstTask他のプロジェクトのビルドファイルで使用できる独自の Ant タスク ( ) を作成しようとしていますbuild.xml。これを行うには、Ant タスクを独自の JAR 内にコンパイルしてパッケージ化する必要があります。私が作成したこの Ant タスクはかなり複雑であるため、XStream を OX マッピングに使用したり、Guice を DI に使用したりするなど、約 20 の依存関係 (他の JAR ファイル) があります。

現在、MyFirstTask プロジェクト内のファイル (再利用可能な Ant タスクであるパッケージ化されるビルドファイル) にpackageタスクを記述しています。build.xmlmyfirsttask.jar

Java JARの意図を完全には理解していないことに突然気付きました。JAR に依存関係を含めるべきではなく、必要な依存関係を提供するためにランタイム構成 (アプリ コンテナー、ランタイム環境など) に任せるべきでしょうか? この場合、実行可能な JAR はルールの例外であると思います。

それとも、Java JAR にその依存関係も含めることを意図しているのでしょうか?

いずれにせよ、ユーザーに 25 個以上の JAR を Ant ライブラリにコピー アンド ペーストすることを強制したくありません。それはただ残酷です。classes/依存関係のクラスパスがディレクトリの下に定義されている WAR ファイルのセットアップ方法が気に入っています。

最終的には、JAR 構造を次のようにしたいと思います。

myfirsttask.jar/
    com/  --> the root package of my compiled binaries
    config/  --> config files, XML, XSD, etc.
    classes/  --> all dependencies, guice-3.0.jar, xstream-1.4.3.jar, etc.
    META-INF/
        MANIFEST.MF

これを達成するために (そして実行時のクラスパスもclasses/ディレクトリを参照するようにするには)、何らかの方法で MANIFEST.MF を変更する必要があると思います (マニフェスト属性が と呼ばれていることは知っていClassPathますよね?)。すべてをまとめるのに苦労しているだけで、そもそも JAR の意図そのものについて迫りくる/長引く疑問があります。

Oracle が JAR に依存関係を含めることを意図しているかどうかを誰か確認できますか? いずれにせよ、マニフェスト (または他の場所) で、実行時にクラスパスがclasses/ディレクトリに格納されている依存関係を見つけられるようにするために何をしなければならないでしょうか? 前もって感謝します!

4

5 に答える 5

3

Java JAR が独自の依存関係を含むことは正しいですか、それとも正しくありませんか?

JAR ファイルに独自の依存関係を含めることが正しいユース ケースがあります。最新の依存関係管理を使用しないユーザーをサポートしたい場合は、Ant タスク コードとすべての依存関係を含む JAR ファイルを提供することをお勧めします。より強力で柔軟なモジュール式のアプローチは、バージョン管理された JAR ファイルをプロジェクト コードのみを含むMaven リポジトリに公開することです。

1) プロジェクト コードとすべての依存関係を含む JAR ファイル

長所

  • ダウンロードは簡単で、エンド ユーザーの唯一のセットアップは <taskdef>、Ant ビルド ファイルにを含めることです。
  • Maven アーティフィケーションを公開するためのセットアップは不要

JAR をビルドする Ant ターゲットの例

<target name="jar" depends="compile"
    description="Creates a standalone JAR of all class files and dependencies.">
  <jar destfile="${my.ant.task.jar.file}" update="true">
    <fileset dir="${build.classes.dir}" />
    <zipfileset src="${lib.dir}/javax.inject.jar" />
    <zipfileset src="${lib.dir}/guice-3.0.jar" />
    <zipfileset src="${lib.dir}/guice-multibindings-3.0.jar" />
    <zipfileset src="${lib.dir}/guice-assistedinject-3.0.jar" />
  </jar>
</target>

短所

  • Ant タスクのエンド ユーザーがプロジェクトに含まれる依存関係の一部またはすべてを既に持っている場合、依存関係の冗長なコピーが作成されることになります。
  • JAR ファイルが非常に大きくなる可能性があります

2) Maven リポジトリに公開されたプロジェクト コードのみを含む JAR ファイル

長所

  • ユーザーは、Maven リポジトリーにパブリッシュした Ant タスクの任意のバージョンを取得できます。これにより、タスクの新しいバージョンをリリースする際の柔軟性が向上し、既存のユーザーは以前のバージョンを引き続き使用して、リグレッションの可能性を回避できます。
  • 共通の依存関係の重複コピーを回避します (依存関係のバージョンが異なるとエラーが発生する場合を除く)
  • JARファイルは小さい

短所

以下について学ぶ必要があります。


参考までに、Java™ チュートリアルには JAR ファイルの概要が記載されています。

レッスン: プログラムを JAR ファイルにパッケージ化する

Java™ Archive (JAR) ファイル形式を使用すると、複数のファイルを 1 つのアーカイブ ファイルにまとめることができます。通常、JAR ファイルには、アプリケーションに関連付けられたクラス ファイルと補助リソースが含まれてい ます

JAR ファイル形式には多くの利点があります。

  • セキュリティ: JAR ファイルのコンテンツにデジタル署名を付けることができます...
  • ダウンロード時間の短縮: アプレットが JAR にバンドルされている場合...
  • 圧縮: JAR 形式を使用すると、ファイルを圧縮して効率的に保存できます。
  • 拡張機能のパッケージ化: 拡張機能フレームワークは、Java コア プラットフォームに機能を追加できる手段を提供し、JAR ファイル形式は拡張機能のパッケージ化を定義します...
  • パッケージの封印: JAR ファイルに格納されたパッケージは、パッケージがバージョンの一貫性を確保できるように、必要に応じて封印することができます。JAR ファイル内にパッケージを封印するということは、そのパッケージで定義されているすべてのクラスが同じ JAR ファイル内にある必要があることを意味します。
  • パッケージのバージョン管理 : JAR ファイルには、ベンダーやバージョン情報など、含まれるファイルに関するデータを保持できます。
  • 移植性: JAR ファイルを処理するメカニズムは、Java プラットフォームのコア API の標準部分です。
于 2012-09-30T20:05:33.567 に答える
3

「JAR ファイル」という用語は、少なくとも 2 つの意味を持ちます。つまり、その意味には少なくとも 2 つの側面があります。最も基本的には、コンテナー形式を意味します。基本的には、META-INF ディレクトリを含む ZIP ファイルです。より厳密に言えば、このコンテナーがクラス ファイルをパッケージ化する方法として使用されることを意味します。

容器であるという意味では、内容に関して意図はありません。ファイルには、クラス ファイル、その他の JAR (いずれかの意味で!) などを含めることができます。しかし、コードのパッケージ化という意味では、JAR ファイルの適切な意図は、依存関係を含まないようにすることだと思います。

JAR File Specificationを読んだことがあれば、クラス ファイルの保存に関するいくつかの暗示があることがわかりますが、他の JAR ファイルの保存については何も言及されていません。それに対応して、JRE での JAR ファイル クラスローダーの実装を見ると、ネストされた JAR では何も役に立ちません。

さらに、JAR 仕様では、ネストされていない依存関係を処理するためのメカニズムであるClass-Path属性について詳しく説明しています。これにより、JAR ファイルはファイルシステム内の他の JAR ファイルへの相対参照を作成できます。

さて、パッケージ感覚の JAR ファイルは、コンテナ感覚の JAR ファイルの唯一の用途ではありません。WAR、EAR、および RAR ファイル (およびその他のファイル) はすべて、特定の目的で使用される JAR ファイルです。それらのそれぞれは、他の JAR を含むことできます。WAR は、パッケージの意味での JAR ファイルを含むことができ、EAR は、それらと WAR を含むことができます。ただし、これらは、パッケージの意味での JAR ファイルとはまったく異なります。それらを利用するには、Java 標準ライブラリにはない特別なクラスローダーが必要であることに注意してください。

WAR などで多くの JAR ファイルをまとめて収集できる方法は非常に便利ですが、Java EE 以外の Java でこれを行うための一般的なメカニズムがないのは本当に残念です。単純にいくつかの JAR をバンドルした「ア​​プリケーション アーカイブ」または「メタ アーカイブ」形式があれば素晴らしいことです。

そのため、プラグインを使用するためにユーザーが 25 個の JAR を必要とするという問題が残ります。おおよそ 2 つのオプションがあります。

まず、苦労を受け入れて、プラグインを JAR でいっぱいの zip として配布します。これはユーザーが解凍する必要があります。

次に、21 世紀に入り、依存関係を自動的に処理するビルド ツールと配布メカニズムを使用します。実際には、Gradle、Maven、またはその他のツール (Ant など) を Ivy と連携して使用して、依存関係を取得します。 Maven Central に移動し、それらの依存関係をリストした POM ファイルとともにコードをリリースします。その後、ユーザーは JAR と POM をダウンロードし、独自のビルド ツールで依存関係を取得できます。

2 番目のルートに進む場合は、自動依存関係管理を使用していないユーザーのために、依存関係の zip もリリースするのが賢明かもしれません。

于 2012-09-30T16:37:19.023 に答える
3

その意図 (AFAIU) は、JAR ファイルがネイティブ コード共有オブジェクト ファイル ( .soUnix 上、.dllWindows 上) のように動作することです。通常、アプリケーションは複数の共有オブジェクト ファイルを兄弟としてインストールし、さらにそれらを起動するための実行ファイルをインストールします。

実行可能な JAR はスタンドアロンの実行可能ファイルに似ているため、すべての依存関係を含めることがより一般的です (静的にリンクされたネイティブ コードの実行可能ファイルにすべての依存オブジェクトを直接含める方法と同様)。

残念ながら、デフォルトの ClassLoader はネストされた JAR からクラスをロードできません。それを行う ClassLoader を作成することは可能です。または、他の誰かが書いたものを使用することもできます。問題の説明から、Jar Jar Linksがまさに探しているものであるように思えます。

于 2012-09-30T14:59:05.847 に答える
1

「Jar Jar Links」はスタンドアロン アプリケーションにのみ適しています。しかし、Ant ではありません。プロジェクトに同じ依存関係があり、後で xstream-*.jar などの新しいバージョンにアップグレードされた場合、競合が発生し、間違ったバージョンが選択される可能性があります。最悪の場合、MethodNotFoundException が発生します。そのため、単一の jar に依存関係を含めることはお勧めできません。

「ユーザーに 25 個以上の JAR をコピー アンド ペーストすることを強制したくない」という問題は何ですか?

それが最も簡単な解決策です。そして、将来の問題を回避できるので、最高です。

ここで、Ant の不便さに気付いたら、Gradle と比較したくなるかもしれません。Gradle を使用すると、Ant に少し似たタスクを取得でき、依存関係の jar を提供する必要はありません。すべての依存関係は Gradle を解決します。Ant と同様に、タスクを作成することもできます。

于 2012-09-30T15:24:55.653 に答える
0

一部のJavaアプリケーションベンダーは、次のシナリオを使用して、他のjarに依存するアプリケーションを配布します。これは、静的リンクを思い出させます。jarを構築する段階で、すべての依存関係(jarも含む)が解凍されます。最終的なjarを作成するときは、新しくコンパイルされたクラスと依存関係から抽出されたクラスの両方が含まれます。

考えられる問題:

  1. ライブラリはアプリに含まれているため、アプリケーションはライブラリを再利用できません。通常の静的リンクの問題。
  2. 再パックされたライブラリのライセンスを尊重する必要があります。通常はそれらを再梱包しても問題ありませんが、場合によってはライセンスファイルに追加の注意を払う必要があります。これはたまたまjarファイル内にある可能性があります。

ちなみに、jarをjar内に含めることはできません。そうしないと、それらのクラスパスを指定できなくなります。したがって、再梱包手順。

于 2012-09-30T18:42:46.123 に答える