web-dev-qa-db-ja.com

Javaクラスパス内のディレクトリにすべてのjarを含める

クラスパス内のディレクトリ内にすべてのjarファイルを含める方法はありますか?

私はJava -classpath lib/*.jar:. my.package.Programを試していますが、これらのjarファイルに確実に含まれるクラスファイルを見つけることができません。各jarファイルをクラスパスに別々に追加する必要がありますか?

921
Chris Serra

Java 6以降を使用して、classpathオプションはワイルドカードをサポートします。次の点に注意してください。

  • 二重引用符を使用("
  • *ではなく*.jarを使用

Windows

Java -cp "Test.jar;lib/*" my.package.MainClass

Unix

Java -cp "Test.jar:lib/*" my.package.MainClass

これはWindowsと似ていますが、:の代わりに;を使用します。ワイルドカードを使用できない場合、bashでは次の構文を使用できます(libはすべてのJavaアーカイブファイルを含むディレクトリです)。

Java -cp $(echo lib/*.jar | tr ' ' ':')

(クラスパスを使用することは-jarオプションと互換性がないことに注意してください。参照: コマンドプロンプトから複数のクラスパスライブラリを含むjarファイルを実行

ワイルドカードについて

Classpath ドキュメントから:

クラスパスエントリには、ベース名のワイルドカード文字*を含めることができます。これは、ディレクトリ内のすべてのファイルのリストを拡張子.jarまたは.JARで指定するのと同等と見なされます。たとえば、クラスパスエントリfoo/*は、fooという名前のディレクトリ内のすべてのJARファイルを指定します。単に*からなるクラスパスエントリは、現在のディレクトリ内のすべてのjarファイルのリストに展開されます。

*を含むクラスパスエントリは、クラスファイルと一致しません。単一のディレクトリfoo内のクラスとJARファイルの両方を一致させるには、foo;foo/*またはfoo/*;fooを使用します。選択された順序によって、foo内のクラスとリソースがfoo内のJARファイルの前にロードされるか、またはその逆かが決まります。

サブディレクトリは再帰的には検索されません。たとえば、foo/*はJARファイルをfooでのみ検索し、foo/barfoo/bazなどでは検索しません。

ディレクトリ内のJARファイルが展開されたクラスパスに列挙される順序は指定されておらず、プラットフォームごとに、場合によっては同じマシン上でも変わる可能性があります。うまく構成されたアプリケーションは、特定の順序に依存してはいけません。特定の順序が必要な場合は、JARファイルをクラスパスに明示的に列挙できます。

ワイルドカードの拡張は、クラスローディングプロセス自体の間ではなく、プログラムのメインメソッドが呼び出される前に行われます。ワイルドカードを含む入力クラスパスの各要素は、指定されたディレクトリ内のJARファイルを列挙することによって生成された(おそらく空の)一連の要素に置き換えられます。たとえば、ディレクトリfooa.jarb.jar、およびc.jarが含まれている場合、クラスパスfoo/*foo/a.jar;foo/b.jar;foo/c.jarに展開され、その文字列はシステムプロパティJava.class.pathの値になります。

CLASSPATH環境変数は、-classpath(または-cp)コマンドラインオプションとの違いはありません。つまり、これらすべての場合にワイルドカードが使用されます。ただし、クラスパスのワイルドカードはClass-Path jar-manifestヘッダーでは使用されません。

注:Java 8の既知のバグのため、ウィンドウの例では末尾にアスタリスクを付けてエントリーの前にバックスラッシュを使用する必要があります。 https://bugs.openjdk.Java.net/browse/JDK-8131329

1059
basszero

窓の下でこれは働く:

Java -cp "Test.jar;lib/*" my.package.MainClass

これはうまくいきません。

Java -cp "Test.jar;lib/*.jar" my.package.MainClass

* .jar、 に注意してください。*ワイルドカードは単独で使うべきです


Linuxでは、次のように動作します。

Java -cp "Test.jar:lib/*" my.package.MainClass

区切り文字はセミコロンではなくコロンです。

214
davorp

この問題を回避するには、クラスパスを指定する manifest myapp.jar)ファイルを含む main jarファイルManifest.mfを展開します。この場合、コードを実行するときにJava -jar myapp.jarを宣言するだけです。

そのため、メインのjarをなんらかのディレクトリにデプロイしてから、依存jarをその下のlibフォルダに配置すると、マニフェストは次のようになります。

Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar

NB:これはプラットフォームに依存しません - 同じjarを使ってUNIXサーバーやWindows PCで起動することもできます。

63
oxbow_lakes

"lib"ディレクトリにすべてのjarファイルを持つJava-Sun 1.6.0_24を使用したUbuntu 10.04上の私の解決策:

Java -cp。:lib/* my.main.Class

これが失敗した場合は、次のコマンドが機能するはずです(libディレクトリ内のすべての* .jarsをクラスパスパラメータに出力します)。

Java -cp $(lib/*。jar内のiの場合、echo -n $ i:; doneを実行します)。 my.main.Class
42
Habi

短い答え:Java -classpath lib/*:. my.package.Program

Oracleでは、クラスパスでのワイルドカードの使用に関するドキュメントを提供しています ここでJava 6の場合 および ここでJava 7の場合 、セクション見出しクラスパスのワイルドカードを理解する。 (私がこれを書いているとき、2つのページには同じ情報が含まれています。)ここにハイライトの要約があります。

  • 一般に、特定のディレクトリにすべてのJARを含めるには、ワイルドカード*not*.jar)を使用できます。 。

  • ワイルドカードはJARにのみ一致し、クラスファイルには一致しません。ディレクトリ内のすべてのクラスを取得するには、ディレクトリ名でクラスパスエントリを終了します。

  • 上記の2つのオプションを組み合わせて、ディレクトリ内のすべてのJARファイルとクラスファイルを含めることができ、通常のクラスパス優先規則が適用されます。例えば。 -cp /classes;/jars/*

  • ワイルドカードは、サブディレクトリ内のJARをnot検索します。

  • 上記の箇条書きは、CLASSPATHシステムプロパティ、または-cpまたは-classpathコマンドラインフラグを使用する場合に当てはまります。ただし、Class-Path JARマニフェストヘッダーを使用する場合(antビルドファイルを使用する場合と同様)、ワイルドカードはnotを受け入れます。

はい、私の最初のリンクはトップスコアの回答で提供されたものと同じです(これを追い越す見込みはありません)が、その回答はリンクを超えて多くの説明を提供しません。そのような動作は discouraged Stack Overflow these days なので、私はそれを拡張すると思った。

32
Pops

私にとってこれはウィンドウズで動作します。

Java -cp "/lib/*;" sample

Linux用

Java -cp "/lib/*:" sample

Java 6 を使っています

32
SANN3

あなたはJavaを試すことができます-Djava.ext.dirs=jarDirectoryhttp://docs.Oracle.com/javase/6/docs/technotes/guides/extensions/spec.html

Java実行時の外部jarディレクトリ

25
Navi

正しい

Java -classpath "lib/*:." my.package.Program

間違っている:

Java -classpath "lib/a*.jar:." my.package.Program
Java -classpath "lib/a*:."     my.package.Program
Java -classpath "lib/*.jar:."  my.package.Program
Java -classpath  lib/*:.       my.package.Program
21
rvernica

ウィンドウズ

 Java -cp file.jar;dir/* my.app.ClassName

Linux

 Java -cp file.jar:dir/* my.app.ClassName

思い出させる:
- Windows パスの区切り文字は;です
- Linux パスの区切り文字は:です
- Windowsでは、cp引数に空白が含まれていない場合、 "引用符"はオプションです。

20
Wender

本当にすべての.jarファイルを動的に指定する必要がある場合は、シェルスクリプト、または Apache Ant を使用できます。 Commons Launcher と呼ばれるcommonsプロジェクトがあります。これは基本的にあなたが起動スクリプトをantビルドファイルとして指定することを可能にします(私が言っていることがわかるなら)。

その後、次のように指定できます。

<path id="base.class.path">
    <pathelement path="${resources.dir}"/>
    <fileset dir="${extensions.dir}" includes="*.jar" />
    <fileset dir="${lib.dir}" includes="*.jar"/>
</path>

起動ビルドファイルで、正しいクラスパスを使用してアプリケーションを起動します。

9
user7094

Java 6を使用している場合は、クラスパスにワイルドカードを使用できます。

クラスパス定義でワイルドカードを使用することが可能になりました。

javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.Java  -d build/classes

Ref: http://www.rekk.de/bloggy/2008/add-all-jars-in-a-directory-to-classpath-with-Java-se-6-using-wildcards/ /

9
prakash

Windows上のJava 7では、ワイルドカード拡張は機能しません。

このStackOverflowの問題 /をチェックしてください。

これを回避するには、ワイルドカードの直後にセミコロンを付けます。 Java -cp "somewhere/*;"

8
Jake Toronto

ご担当者様、

私はMSYS/MinGWシェルの下でWindows上でこの奇妙な振る舞いを見つけました。

作品:

$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.Java

動作しません:

$ javac -cp 'c:\Programs\COMSOL44\plugins\*' Reclaim.Java
javac: invalid flag: c:\Programs\COMSOL44\plugins\com.comsol.aco_1.0.0.jar
Usage: javac <options> <source files>
use -help for a list of possible options

ワイルドカードがシェルによって拡張されないことは確かです。

$ echo './*'
./*

(組み込みのechoではなく、他のプログラムでも同じ結果を得ました。)

私はそれを拡張しようとしているのはjavacだと思います、そしてそれは引数の中にセミコロンがあるかどうかによって異なった振る舞いをします。まず、パスのように見えるすべての引数を拡張しようとしている可能性があります。そしてその時になって初めて-cpは次のトークンのみを取り、それらを解析します。 (com.comsol.aco_1.0.0.jarがそのディレクトリの2番目のJARであることに注意してください。)それはすべて推測です。

これは

$ javac -version
javac 1.7.0
6
Evgeni Sergeev

Windowsの場合は引用符が必要です。区切り文字として使用する必要があります。例えば。:

Java -cp "target\\*;target\\dependency\\*" my.package.Main
4
Alexey

短縮形:メインがjar内にある場合は、( 'YourJarsName.jar'がクラスパスにあったとしても)それを機能させるために明示的に宣言された追加の '-jar pathTo/yourJar/YourJarsName.jar'がおそらく必要です。 、5年前に尋ねられた最初の質問に答えるために表明:あなたは明示的に各jarファイルを再宣言する必要はありませんが、Java6でもあなた自身のjarファイルを再宣言する必要があるようです...)


長形式:(Javaへの侵入者でもこれを利用できることを願ってこの点を明示しました)

私はここで多くの人がEclipseを使ってjarをエクスポートしています:(File-> Export - > 'Runnable JAR File')。 Eclipse(Juno)が提供する「ライブラリ処理」には3つのオプションがあります。

opt1: "Extract required libraries into generated JAR"
opt2: "Package required libraries into generated JAR"
opt3: "Copy required libraries into a sub-folder next to the generated JAR"

通常私はopt2を使用します(そしてopt1は間違いなく壊れています)が、私が使用しているjarファイルの1つにネイティブコードがあります。このオプションを選択するとEclipseが利用する便利な「jarinjar」トリックで壊れます。 opt3が必要であることに気づいた後で、このStackOverflowエントリを見つけても、Eclipseの外部でメインを起動する方法を理解するのにはまだ時間がかかりました。


Jarに "fooBarTheJarFile.jar"という名前を付け、allがディレクトリにエクスポートするように設定されている場合: "/ theFully/qualifiedPath/toYourChosenDir"。

(「エクスポート先」フィールドは「/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar」となります)

終了すると、Eclipseはすべてのライブラリをそのエクスポートディレクトリ内の 'fooBarTheJarFile_lib'という名前のフォルダに配置します。

/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar01.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar02.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar03.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar04.jar

その後、システムのどこからでも起動できます。

Java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" -jar  /theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar   package.path_to.the_class_with.your_main.TheClassWithYourMain

(Java初心者のために: 'package.path_to.the_class_with.your_main'は 'main(String [] args){..を含む' TheClassWithYourMain.Java 'ファイルの一番上にある宣言されたpackage-pathです。 Javaの外部から実行したい


注意すべき落とし穴は、宣言されたクラスパスのjarのリスト内に 'fooBarTheJarFile.jar'を含めるだけでは不十分であるということです。あなたは明示的に '-jar'を宣言し、そのjarファイルの位置を再宣言する必要があります。

例えばこれは壊れます:

 Java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*"  somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain

相対パスで言い換えると、

cd /theFully/qualifiedPath/toYourChosenDir/;
BREAKS:  Java -cp "fooBarTheJarFile_lib/*"                                package.path_to.the_class_with.your_main.TheClassWithYourMain    
BREAKS:  Java -cp ".;fooBarTheJarFile_lib/*"                              package.path_to.the_class_with.your_main.TheClassWithYourMain   
BREAKS:  Java -cp ".;fooBarTheJarFile_lib/*"   -jar                       package.path_to.the_class_with.your_main.TheClassWithYourMain   
WORKS:   Java -cp ".;fooBarTheJarFile_lib/*"   -jar  fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain   

(Javaバージョン "1.6.0_27"を使用。Ubuntu12.04のOpenJDK 64ビットサーバーVMを介して)

4
Matt S.

EclipseやNetbeansのようなIDEの外部でJavaアプリケーションを開発して実行する場合、上記のすべての解決策は非常に役立ちます。

Windows 7を使用していて、Javaでの開発にEclipse IDEを使用した場合、コマンドプロンプトを使用してEclipse内に構築されたクラスファイルを実行すると問題が発生する可能性があります。

例えば。 Eclipseのソースコードは次のようなパッケージ階層を持っています。edu.sjsu.myapp.Main.Java

Main.Javaの外部依存関係としてjson.jarがあります。

Eclipse内からMain.Javaを実行しようとすると、問題なく実行されます。

しかし、EclipseでMain.Javaをコンパイルした後にコマンドプロンプトを使用してこれを実行しようとすると、 "ClassNotDef Error blah blah"という奇妙なエラーが発生します。

私はあなたがあなたのソースコードの作業ディレクトリにいると思います!

コマンドプロンプトから実行するには、次の構文を使用します。

  1. javac -cp "。; json.jar" Main.Java

  2. Java -cp "。; json.jar" edu.sjsu.myapp.Main

    [お見逃しなく。上記]

これは、Main.Javaをパッケージedu.sjsu.myapp内に配置したため、Java.exeが正確なパターンを検索するためです。

それが役に立てば幸い !!

4
realPK

私が知っている唯一の方法はそれを個別に行うことです、例えば:

setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.

それが役立つことを願っています!

3
ParseTheData

wepappのクラス:

  > mvn clean install

  > Java -cp "webapp/target/webapp-1.17.0-SNAPSHOT/WEB-INF/lib/tool-jar-1.17.0-SNAPSHOT.jar;webapp/target/webapp-1.17.0-SNAPSHOT/WEB-INF/lib/*" com.xx.xx.util.EncryptorUtils param1 param2
3
Mindaugas K.

/ *を-cpに設定できるようにする直接的な解決策ではありませんが、動的クラスパスおよびlibディレクトリの場合には、状況を少し緩和するために次のスクリプトを使用できると思います。

 libDir2Scan4jars="../test";cp=""; for j in `ls ${libDir2Scan4jars}/*.jar`; do if [ "$j" != "" ]; then cp=$cp:$j; fi; done; echo $cp| cut -c2-${#cp} > .tmpCP.tmp; export tmpCLASSPATH=`cat .tmpCP.tmp`; if [ "$tmpCLASSPATH" != "" ]; then echo .; echo "classpath set, you can now use  ~>         Java -cp \$tmpCLASSPATH"; echo .; else echo .; echo "Error please check libDir2Scan4jars path"; echo .; fi; 

Linux用にスクリプト化されていて、Windows用にも同様のものがあります。適切なディレクトリが "libDir2Scan4jars"への入力として提供されている場合。スクリプトはすべてのjarファイルをスキャンしてクラスパス文字列を作成し、それをenv変数 "tmpCLASSPATH"にエクスポートします。

2
Sreesankar

複数のjarファイルと現在のディレクトリのクラスファイルに適した方法でクラスパスを設定します。

CLASSPATH=${Oracle_HOME}/jdbc/lib/ojdbc6.jar:${Oracle_HOME}/jdbc/lib/ojdbc14.jar:${Oracle_HOME}/jdbc/lib/nls_charset12.jar; 
CLASSPATH=$CLASSPATH:/export/home/gs806e/tops/jconn2.jar:.;
export CLASSPATH

あなたはそれらをすべて別々に追加する必要があります。あるいは、 本当に ディレクトリを指定するだけでよい場合は、すべてを1つのディレクトリに展開してクラスパスに追加することができます。ただし、クラスパスのバージョン管理や管理しにくいという点で奇妙な問題が発生する可能性があるため、この方法はお勧めしません。

1
Daniel Spiewak

Jarファイルをディレクトリ構造のルートとして考えます。はい、あなたはそれらをすべて別々に追加する必要があります。

1
R. Van Hoose

フォルダに複数のjarファイルがあります。下記のコマンドは私のためにJDK1.8でフォルダーに存在するすべてのjarファイルを含めるように働きました。クラスパスにスペースがある場合は引用符で囲むことに注意してください。

ウィンドウズ

コンパイル:javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.Java

実行中:Java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram

Linux

コンパイル:javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.Java

実行中:Java -classpath "/home/guestuser/My Jars/sdk/lib/*:/home/guestuser/programs" MyProgram

0
vkrams

私はJavaファイルをjarとして、またはUbuntuのクラスとして実行しようとしています。私は両方の選択肢に失敗した。次の例外はその出力です。

Download link: https://upload.cat/f694139f88c663b1

Java org.statmetrics.Statmetric

または

Java -cp /home/elias/statmetrics/statmetrics.jar: org.statmetrics.Statmetrics

または

Javaクラスパス "/usr/lib/jvm/Java-1.8.0-openjdk-AMD64/jre/lib/*" -jar /home/elias/statmeics/statmetrics.jar

Exception in thread "Thread-0" Java.lang.NoClassDefFoundError: javax/xml/bind/annotation/adapters/XmlAdapter
    at Java.base/Java.lang.ClassLoader.defineClass1(Native Method)
    at Java.base/Java.lang.ClassLoader.defineClass(ClassLoader.Java:1016)
    at Java.base/Java.security.SecureClassLoader.defineClass(SecureClassLoader.Java:174)
    at Java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.Java:802)
    at Java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.Java:700)
    at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.Java:623)
    at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:581)
    at Java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:178)
    at Java.base/Java.lang.ClassLoader.loadClass(ClassLoader.Java:521)
    at org.statmetrics.c.a(Unknown Source)
    at org.statmetrics.dw.a(Unknown Source)
    at org.statmetrics.dx.run(Unknown Source)
Caused by: Java.lang.ClassNotFoundException: javax.xml.bind.annotation.adapters.XmlAdapter
    at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:583)
    at Java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:178)
    at Java.base/Java.lang.ClassLoader.loadClass(ClassLoader.Java:521)
    ... 12 more

私は答えを見つけました:

私の愚かさ.

最初のステップ:あなたは対応するJavaをセットしなければなりません:私はJava 11を持っていました、しかし私はJava libパスとして第8バージョンをセットしました! - ここからJavaのバージョンを設定できます。

  Sudo update-alternatives --config Java

第2ステップ:次に、パスとファイル名を対応するパスとファイルに変更して、次のコマンドを実行します。

  Java -classpath "/usr/lib/jvm/Java-1.8.0-openjdk-AMD64/jre/lib/*" -jar /home/elias/statmetrics/statmetrics.jar org.statmetrics.Statmetrics

正常に実行されました。

0