![](/img/trans.png)
[英]Java use -classpath to include multiple jars in multiple directories all in one directory?
[英]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/bar
、foo/baz
等中查找。目錄中的 JAR 文件在擴展類路徑中枚舉的順序沒有指定,並且可能因平台而異,甚至在同一台機器上有時也會不同。 一個構建良好的應用程序不應依賴於任何特定的順序。 如果需要特定順序,則可以在類路徑中顯式枚舉 JAR 文件。
在類加載過程本身期間,通配符的擴展在調用程序的主要方法之前進行,而不是在后期進行。 包含通配符的輸入類路徑的每個元素都被替換為通過枚舉指定目錄中的 JAR 文件生成的(可能為空的)元素序列。 例如,如果目錄
foo
包含a.jar
、b.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 中的一個已知錯誤,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 參數不包含空格,則“引號”是可選的
你可以試試 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”。
我假設您在源代碼的工作目錄中!!
使用以下語法從命令提示符運行它:
javac -cp ".;json.jar" Main.java
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 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.