JAR内のJARを含むクラスパス


回答:


94

アプリケーションと必要なライブラリーを含む単一のjarを作成しようとしている場合、それを行うには2つの方法(私が知っている)があります。1 One-Jarで、特別なクラスローダーを使用してjarのネストを可能にします。もう1つはUberJar(またはShade)で、含まれているライブラリを分解し、すべてのクラスを最上位のjarに入れます。

また、UberJarとShadeはそれぞれMaven1とMaven2のプラグインであることにも触れておきます。以下で説明するように、アセンブリプラグインを使用することもできます(実際には非常に強力ですが、適切に構成するのははるかに困難です)。


81
だからここに、5年後です。これはまだ正しいようです。非常に悲しい:(
T3rm1 2013

3
私が今日知っている最良の方法は、IntelliJ jarアーティファクトを使用することです。依存するjarからすべてのクラスを抽出し、それらを1つのjarに入れます。
enl8enmentnow 2014年

2
これは、署名が必要なBouncyCastleなどのJCE実装を使用している場合など、状況によっては
不可能です

1
@ BrainSlugs83 ...何をしようとしていますか?One-Jarのクラスローダーとパッケージャーは、JarをJar(Java SEの場合)プロジェクトに含めることに対する答えです。UberJarを使用すると、クラスファイルをJarに抽出することで問題が解消されます。
スティーブモイヤー2014年

1
UberJarリンクにはログイン資格情報が必要です。後継のウェブページはありますか?
Thomas Weller

50

これらの「JARコンテンツの分解」ソリューションを使用したくない。彼らは間違いなくものを見るのを難しくします(すべてが同じレベルで分解されるので)。さらに、名前の競合が発生する可能性があります(適切なパッケージを使用している場合は発生しないはずですが、これを常に制御できるわけではありません)。

あなたが望むことを特徴としての一つであるトップ25日のRFERFE 4648386、Sunは、その無限の知恵で、優先度が低いものとして指定しています。私たちは太陽が目を覚ますことを望みます...

その間、私が遭遇した最良の解決策(SunがJDKにコピーすることを望む)は、カスタムクラスローダーJarClassLoaderを使用することです


4
名前の競合は、log4jの構成やライセンステキストなどで発生することがほぼ保証されています。
Michael Borgwardt、2011年

1
悲しいことに、JarClassLoaderはGPLv3 / commercialなので、おそらく「太陽(現在のオラクル)によってコピー」されることはなく、内部の政治的影響力と何かを購入する時間がない限り、商業的に使用することはできません。ただし、現在のディレクトリでbarfを実行するjarは悪いものであることに同意します。
Gus

この回答のアイデアを+1します(私は回答自体を+1しません):署名されたJARファイルを再パッケージ化できないため、この手法は多くの状況(Javaなど)で使用できませんactivation.jar)。
クリストファーシュルツ2016年

31

いくつかの調査の結果、Mavenやサードパーティの拡張機能やプログラムを必要としない方法が見つかりました。

マニフェストファイルで「Class-Path」を使用できます。

例えば:

マニフェストファイルMANIFEST.MFを作成する

Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass

すべてのクラスをコンパイルして実行します jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

ccreate archive fは、ファイルvを詳細な入力用 に指定 mすることを意味し、カスタムマニフェストファイルを渡すことを意味します。

jarパッケージにlibが含まれていることを確認してください。jarを通常の方法で実行できるはずです。

ベース:http : //www.ibm.com/developerworks/library/j-5things6/

クラスパスについて必要な他のすべての情報はここにありますか


19
この回答は機能しませ。oracle doc(上記のバナナでリンク)から:「Class-Pathヘッダーは、JARファイル内のJARファイルではなく、ローカルネットワーク上のクラスまたはJARファイルを
指し

これがAndroidの設定でも使用できるかどうかはわかっています。
モストウスキー崩壊

2
実行可能なjarシナリオ(テスト済み)で機能しますが、jarをライブラリjarに含めたい場合は機能しない可能性があります。
Cychih

5
ああ、それは機能しません。いったんcustom_lib.jar離れてしまうと、jarはもう実行できません:(
Cychih

Class-Pathで複数のjarを指定するにはどうすればよいですか?
Abhishek Tiwari

22

使用zipgroupfilesetタグ(用途と同じ属性ファイルセットタグ)。ディレクトリ内のすべてのファイルを解凍し、新しいアーカイブファイルに追加します。詳細:http : //ant.apache.org/manual/Tasks/zip.html

これはjar-in-a-jarの問題を回避するのに非常に便利な方法です-何をすべきかを理解しようとしているときにこの正確なStackOverflowの質問をググったので知っています。jarまたはjarのフォルダーをAntで作成した1つのjarにパッケージ化したい場合は、このクラスパスやサードパーティのプラグインのことをすべて忘れて、これを(Antで)行うだけです。

<jar destfile="your.jar" basedir="java/dir">
  ...
  <zipgroupfileset dir="dir/of/jars" />
</jar>

8

antを使用してビルドしている場合(私はeclipseのantを使用しています)、antに追加するように言って、追加のjarファイルを追加できます...複数の人がプロジェクトを管理しているが、それが機能する場合は、必ずしも最良の方法とは限りません一人のプロジェクトのために、簡単です。

たとえば、.jarファイルを構築していた私のターゲットは次のとおりです。

<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
    <manifest>
        <attribute name="Author" value="ntg"/>
        ................................
        <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
    </manifest>
</jar>

私はそれを作るために1行追加しました:

<jar ....">
    <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
    <manifest>
        ................................
    </manifest>
</jar>

どこ

<property name="external-lib-dir" 
          value="C:\...\eclipseWorkspace\Filter\external\...\lib" />

外部jarファイルのあるdirでした。以上です...


6

独自のクラスローダーを書くことなしではありません。jarのクラスパスにjarを追加できますが、それらはメインjarに含まれていない、同じ場所に配置する必要があります。


2

これを行うには、カスタムクラスローダー、またはこれをサポートするサードパーティライブラリをビルドする必要があります。最善の策は、jarをランタイムから抽出してクラスパスに追加することです(またはクラスパスにすでに追加しておくこと)。


2

Mavenアセンブリプラグインと呼ばれるプラグインを持つJavaビルドにMavenを使用します。。

それはあなたが求めていることを行いますが、他のいくつかの提案が説明しているように-依存するすべてのjarを本質的に分解し、それらを単一のjarに再結合します


Mavenアセンブリプラグインを使用するのはかなり骨が折れる... UberJarとShadeはMaven1とMaven2プラグインです(事実、私は前述したはずですが、今すぐそうします)
Steve Moyer

2

eclpise IDEを使用している場合は、JARをエクスポートして、「必要なライブラリを生成されたJARにパッケージ化」を選択するだけです。eclipseは、必要な依存JARを生成されたJARに自動的に追加し、これらのJARを自動的にロードするeclipseカスタムクラスローダーを生成します。


1

すべてのファイルを同じレベルで抽出し、その結果からjarを作成することをお勧めしました。パッケージシステムはそれらをきれいに分離しておく必要があるためです。それは手動の方法でしょう。Steveによって示されたツールがそれをうまく行うと思います。



1

まあ、Eclipseを使用している場合は非常に簡単な方法があります。

プロジェクトを「実行可能な」Jarファイルとしてエクスポートします(Eclipse内からプロジェクトフォルダーを右クリックし、[エクスポート...]を選択します)。エクスポート設定を構成するときは、[必要なライブラリを生成されたJARに抽出する]を選択してください。「Package required libraries ...」ではなく、「Extract ...」を選択してください。

さらに:エクスポート設定で実行構成を選択する必要があります。したがって、常にいくつかのクラスで空のmain()を作成し、それを実行構成に使用できます。

とにかく、それは保証されていませ 100%の時間で動作れ。含めるJarファイルのライセンスを確認し、署名ファイルをコピーしないことを確認するように指示するポップアップメッセージが表示されます。しかし、私はこれを何年も行っており、問題に遭遇したことがありません。


0

Uber-dirへの抽出は、すべてroot:\ javaを使用し、バージョニング付きのパッケージにアウトレットコードがあるため、私にとってはうまくいきます。つまり、ca.tecreations-1.0.0です。jarはダウンロードした場所からそのままなので、署名は問題ありません。サードパーティの署名はそのままで、c:\ javaに抽出します。私のプロジェクトディレクトリがあります。ランチャーから実行するので、java -cp c:\ java Launcher


したがって、c:\ java \ jarsにjarします。c:\ javaのソース、バイナリ、リソース。バックアップ、プロパティ、keystore_privateを除外します。c:\ javaに解凍し、クラスパス形成ツールを使用して実行します。したがって、おそらくca.tecreations.system.tools.SystemToolまたは同等のjavaクラスです。それを実行します。
Tim de Vries、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.