簡體   English   中英

在 Java 類路徑中的目錄中包含所有 jar

[英]Including all the jars in a directory within the Java classpath

有沒有辦法將所有 jar 文件包含在類路徑的目錄中?

我正在嘗試java -classpath lib/*.jar:. my.package.Program java -classpath lib/*.jar:. my.package.Program並且它無法找到肯定在這些 jars 中的類文件。 我是否需要將每個 jar 文件分別添加到類路徑中?

使用 Java 6 或更高版本,類路徑選項支持通配符。 請注意以下事項:

  • 使用直引號 ( " )
  • 使用* ,而不是*.jar

視窗

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

Unix

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

這類似於 Windows,但使用:而不是; . 如果您不能使用通配符, bash允許使用以下語法(其中lib是包含所有 Java 存檔文件的目錄):

java -cp "$(printf %s: lib/*.jar)"

(請注意,使用類路徑與-jar選項不兼容。另請參閱: 從命令提示符使用多個類路徑庫執行 jar 文件

了解通配符

類路徑文檔:

類路徑條目可以包含基本名稱通配符* ,這被認為等同於指定目錄中所有文件的列表,擴展名為.jar.JAR 例如,類路徑條目foo/*指定名為 foo 的目錄中的所有 JAR 文件。 僅由*組成的類路徑條目擴展為當前目錄中所有 jar 文件的列表。

包含*類路徑條目將不匹配類文件。 要匹配單個目錄 foo 中的類和 JAR 文件,請使用foo;foo/*foo/*;foo 選擇的順序確定是否在類和資源foo中之前在JAR文件加載foo ,或反之亦然。

不遞歸搜索子目錄。 例如, foo/*僅在foo查找 JAR 文件,而不在foo/barfoo/baz等中查找。

目錄中的 JAR 文件在擴展類路徑中枚舉的順序沒有指定,並且可能因平台而異,甚至在同一台機器上有時也會不同。 一個構建良好的應用程序不應依賴於任何特定的順序。 如果需要特定順序,則可以在類路徑中顯式枚舉 JAR 文件。

在類加載過程本身期間,通配符的擴展在調用程序的主要方法之前進行,而不是在后期進行。 包含通配符的輸入類路徑的每個元素都被替換為通過枚舉指定目錄中的 JAR 文件生成的(可能為空的)元素序列。 例如,如果目錄foo包含a.jarb.jarc.jar ,則類路徑foo/*擴展為foo/a.jar;foo/b.jar;foo/c.jar ,並且該字符串將是系統屬性java.class.path的值。

CLASSPATH環境變量的處理方式與-classpath (或-cp )命令行選項沒有任何區別。 也就是說,在所有這些情況下都使用通配符。 但是,在Class-Path jar-manifest標頭中不支持類路徑通配符。

注意:由於 Java 8 中的一個已知錯誤,Windows 示例必須在條目前使用反斜杠並帶有星號: https : //bugs.openjdk.java.net/browse/JDK-8131329

在 Windows 下這有效:

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

分隔符是冒號而不是分號

我們通過部署一個jar 文件myapp.jar來解決這個問題,該文件包含一個清單( Manifest.mf ) 文件,該文件指定了一個帶有其他所需 jar 的類路徑,然后與它一起部署。 在這種情況下,您只需要在運行代碼時聲明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

注意:這是獨立於平台的——我們可以使用相同的 jars 在 UNIX 服務器或 Windows PC 上啟動。

我在 Ubuntu 10.04 上的解決方案使用 java-sun 1.6.0_24 在“lib”目錄中包含所有 jar:

java -cp .:lib/* my.main.Class

如果失敗,則以下命令應該可以工作(將 lib 目錄中的所有 *.jars 打印到類路徑參數)

java -cp $(for i in lib/*.jar ; do echo -n $i: ; done). my.main.Class

簡短回答: java -classpath lib/*:. my.package.Program java -classpath lib/*:. my.package.Program

Oracle 在此處為 Java 6此處為 Java 7 的類路徑中使用通配符提供了文檔,位於標題“理解類路徑通配符”部分下。 (在我撰寫本文時,這兩頁包含相同的信息。)以下是重點摘要:

  • 通常,要在給定目錄中包含所有 JAR,您可以使用通配符*而不是*.jar )。

  • 通配符只匹配 JAR,不匹配類文件; 要獲取目錄中的所有類,只需在目錄名稱處結束類路徑條目。

  • 以上兩個選項可以結合使用,將所有 JAR 和類文件都包含在一個目錄中,並且通常的類路徑優先規則適用。 例如-cp /classes;/jars/*

  • 通配符不會在子目錄中搜索 JAR。

  • 如果您使用CLASSPATH系統屬性或-cp-classpath命令行標志,則上述要點是正確的。 但是,如果您使用Class-Path JAR 清單標頭(就像您使用 ant 構建文件所做的那樣),則不會使用通配符。

是的,我的第一個鏈接與得分最高的答案中提供的鏈接相同(我沒有超越的希望),但該答案在鏈接之外沒有提供太多解釋。 由於這些天在 Stack Overflow 上不鼓勵這種行為,我想我會擴展它。

窗戶

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

Linux

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

提醒:
- Windows路徑分隔符是;
- Linux路徑分隔符是:
- 在 Windows 中,如果 cp 參數不包含空格,則“引號”是可選的

對我來說,這適用於 windows 。

java -cp "/lib/*;" sample

對於 linux

java -cp "/lib/*:" sample

我正在使用Java 6

你可以試試 java -Djava.ext.dirs=jarDirectory http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html

運行java時外部jar的目錄

正確

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

如果您使用的是 Java 6,那么您可以在類路徑中使用通配符。

現在可以在類路徑定義中使用通配符:

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

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

請注意,Windows 上的 Java 7 通配符擴展被破壞。

查看此 StackOverflow 問題以獲取更多信息。

解決方法是在通配符之后放置一個分號。 java -cp "somewhere/*;"

如果您確實需要動態指定所有 .jar 文件,您可以使用 shell 腳本或Apache Ant 有一個名為Commons Launcher的公共項目,它基本上允許您將啟動腳本指定為 ant 構建文件(如果您明白我的意思)。

然后,您可以指定如下內容:

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

在您的啟動構建文件中,它將使用正確的類路徑啟動您的應用程序。

敬啟者,

我在 Windows 上的 MSYS/MinGW shell 下發現了這種奇怪的行為。

作品:

$ 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

我很確定通配符沒有被 shell 擴展,因為例如

$ echo './*'
./*

(也用另一個程序嘗試過,而不是內置的echo ,結果相同。)

我相信是javac試圖擴展它,無論參數中是否有分號,它的行為都不同。 首先,它可能試圖擴展所有看起來像路徑的參數。 只有這樣它才會解析它們, -cp只接受以下標記。 (請注意, com.comsol.aco_1.0.0.jar是該目錄中的第二個 JAR。)這都是猜測。

這是

$ javac -version
javac 1.7.0

如果您在 Eclipse 或 Netbeans 等任何 IDE 之外開發和運行 Java 應用程序,則上述所有解決方案都非常有效。

如果您使用的是 Windows 7 並使用 Eclipse IDE 進行 Java 開發,則在使用命令提示符運行 Eclipse 中構建的類文件時可能會遇到問題。

例如,您在 Eclipse 中的源代碼具有以下包層次結構:edu.sjsu.myapp.Main.java

您有 json.jar 作為 Main.java 的外部依賴項

當您嘗試從 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 將查找確切的模式。

希望能幫助到你 !!

簡短形式:如果您的主要文件在 jar 中,您可能需要額外的 '-jar pathTo/yourJar/YourJarsName.jar ' 明確聲明以使其工作(即使 'YourJarsName.jar' 在類路徑上)(或,表示要回答 5 年前提出的原始問題:您不需要明確重新聲明每個 jar,但似乎確實如此,即使使用 java6,您也需要重新聲明自己的 jar ......)


長格式:(我已經明確指出,我希望即使是 java 的闖入者也可以利用這一點)

像這里的許多人一樣,我使用 eclipse 來導出 jars: (File->Export-->'Runnable JAR File')。 “庫處理”日食(Juno)提供三個選項:

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 中的本機代碼發現使用方便的“jarinjar”技巧會中斷,當您選擇該選項時,eclipse 會利用該技巧。 即使在意識到我需要 opt3,然后找到這個 StackOverflow 條目之后,我仍然花了一些時間來弄清楚如何在 eclipse 之外啟動我的主程序,所以這對我有用,因為它對其他人有用......


如果您將 jar 命名為:“fooBarTheJarFile.jar”,並且所有內容都設置為導出到目錄:“/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){.. .}' 您希望從 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”;通過 ubuntu 12.04 上的 OpenJDK 64 位服務器 VM)

對於 Windows 需要引號和 ; 應該用作分隔符。 例如:

java -cp "target\\*;target\\dependency\\*" my.package.Main

macOS,當前文件夾

對於macOS Mojave上的 Java 13 …

如果所有.jar文件都在同一個文件夾中,請使用cd將其設為當前工作目錄 pwd驗證。

對於-classpath您必須首先列出應用程序的JAR 文件 使用冒號字符:作為分隔符,附加星號*以獲取同一文件夾中的所有其他 JAR 文件。 最后,使用您的main方法傳遞類的完整包名。

例如,對於名為my_app.jar的 JAR 文件中的App在名為com.example的包中名為App的類中有一個main方法,以及同一文件夾中一些需要的 jars:

java -classpath my_app.jar:* com.example.App

來自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

我知道的唯一方法是單獨進行,例如:

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

希望有幫助!

您需要單獨添加它們。 或者,如果您真的只需要指定一個目錄,您可以將所有內容解壓縮到一個目錄中並將其添加到您的類路徑中。 但是,我不推薦這種方法,因為您可能會面臨類路徑版本控制和不可管理性方面的奇怪問題。

不是能夠將 /* 設置為 -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 並創建一個類路徑字符串並將其導出到環境變量“tmpCLASSPATH”。

將 jar 文件視為目錄結構的根。 是的,您需要單獨添加它們。

以適合多個 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

我在一個文件夾中有多個 jars。 以下命令在JDK1.8對我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

我正在嘗試以jar或Ubuntu中的類的形式運行Java文件。 我在兩個選項中都失敗了。 以下例外是其輸出。

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

java org.statmetrics.Statmetric

要么

java -cp /home/elias/statmetrics/statmetrics.jar:。 org.statmetrics.Statmetrics

要么

java -classpath“ /usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/*” -jar /home/elias/statmeics/statmetrics.jar org.statmetrics.Statmetrics

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,但是我將第8版設置為Java lib path! -您可以在此處設置Java版本:

  sudo update-alternatives --config java

第二步:然后,通過將路徑和文件名更改為相應的路徑和文件,運行以下命令:

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

運行成功!

java命令的參數順序也很重要:

c:\projects\CloudMirror>java Javaside -cp "jna-5.6.0.jar;.\"
Error: Unable to initialize main class Javaside
Caused by: java.lang.NoClassDefFoundError: com/sun/jna/Callback

相對

c:\projects\CloudMirror>java -cp "jna-5.6.0.jar;.\" Javaside
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM