有没有办法在类路径的目录中包含所有 jar 文件?
我正在尝试java -classpath lib/*.jar:. my.package.Program
,但它无法找到肯定在这些 jar 中的类文件。我是否需要将每个 jar 文件分别添加到类路径中?
有没有办法在类路径的目录中包含所有 jar 文件?
我正在尝试java -classpath lib/*.jar:. my.package.Program
,但它无法找到肯定在这些 jar 中的类文件。我是否需要将每个 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
选项不兼容。另请参阅:Execute jar file with multiple classpath library from command prompt)
了解通配符
从类路径文档中:
类路径条目可以包含基本名称通配符
*
,这被认为等同于指定目录中所有文件的列表,扩展名为.jar
或.JAR
。例如,类路径条目foo/*
指定名为 foo 的目录中的所有 JAR 文件。一个简单的类路径条目*
扩展为当前目录中所有 jar 文件的列表。包含的类路径条目
*
将不匹配类文件。要匹配单个目录 foo 中的类和 JAR 文件,请使用foo;foo/*
或foo/*;foo
。选择的顺序决定了 中的类和资源是否在foo
中的 JAR 文件之前加载foo
,反之亦然。不递归搜索子目录。例如,
foo/*
仅在 中查找 JAR 文件foo
,而不在foo/bar
,foo/baz
等中查找 JAR 文件。目录中 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 ( Manifest.mf
) 文件,该文件指定一个类路径以及其他所需的 jar,然后将这些 jar 与它一起部署。这种情况下,只需要java -jar myapp.jar
在运行代码时声明即可。
因此,如果您将 main 部署jar
到某个目录中,然后将依赖 jar 放入该lib
目录下的文件夹中,则清单如下所示:
Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar
注意:这是独立于平台的——我们可以使用相同的 jar 在 UNIX 服务器或 Windows PC 上启动。
我在 Ubuntu 10.04 上使用 java-sun 1.6.0_24 的解决方案,所有 jar 都在“lib”目录中:
java -cp .:lib/* my.main.Class
如果失败,以下命令应该可以工作(将 lib 目录中的所有 *.jar 打印到类路径参数中)
java -cp $(for i in lib/*.jar ; do echo -n $i: ; done)。我的主类
简短的回答:java -classpath lib/*:. my.package.Program
Oracle 提供了有关在类路径中使用通配符的文档,此处为 Java 6,此处为 Java 7,标题为“了解类路径通配符”部分。(在我写这篇文章时,这两页包含相同的信息。)以下是重点摘要:
通常,要包含给定目录中的所有 JAR,您可以使用通配符*
( not *.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
如果您确实需要动态指定所有 .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>
在您的启动构建文件中,它将使用正确的类路径启动您的应用程序。
敬启者,
我在 MSYS/MinGW shell 下的 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
我很确定通配符不会被shell扩展,因为例如
$ echo './*'
./*
(也尝试了另一个程序,而不是内置的echo
,结果相同。)
我相信它javac
正在尝试扩展它,并且无论参数中是否有分号,它的行为都会有所不同。首先,它可能试图扩展所有看起来像路径的参数。只有这样它才会解析它们,-cp
只使用以下标记。(请注意,这com.comsol.aco_1.0.0.jar
是该目录中的第二个 JAR。)这都是猜测。
这是
$ javac -version
javac 1.7.0
请注意,Windows 上 Java 7 的通配符扩展被破坏。
查看这个 StackOverflow 问题以获取更多信息。
解决方法是在通配符之后放置一个分号。java -cp "somewhere/*;"
如果您在 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 将查找确切的模式。
希望能帮助到你 !!
对于 windows 报价是必需的,并且 ; 应该用作分隔符。例如:
java -cp "target\\*;target\\dependency\\*" my.package.Main
短格式:如果你的 main 在一个 jar 中,你可能需要一个额外的 '-jar pathTo/yourJar/YourJarsName.jar '明确声明让它工作(即使 'YourJarsName.jar' 在类路径上)(或,表示回答 5 年前提出的原始问题:您不需要明确地重新声明每个 jar,但似乎,即使使用 java6,您也需要重新声明自己的 jar ...)
长格式:(我已经明确表示我希望即使是 Java 的闯入者也可以使用它)
像这里的许多人一样,我使用 eclipse 来导出 jar:(文件->导出->'可运行的 JAR 文件')。'库处理' eclipse (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 中的本机代码发现在您选择该选项时 eclipse 会利用方便的“jarinjar”技巧破坏。即使在意识到我需要 opt3,然后找到这个 StackOverflow 条目之后,我仍然花了一些时间来弄清楚如何在 eclipse 之外启动我的 main,所以这对我有用,因为它对其他人有用......
如果您将 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)
对于macOS Mojave上的 Java 13 ...</p>
如果您的所有.jar
文件都在同一个文件夹中,请使用该文件夹cd
作为您当前的工作目录。用 验证pwd
。
为此,-classpath
您必须首先列出您的应用程序的JAR 文件。使用冒号:
作为分隔符,附加一个星号*
以获取同一文件夹中的所有其他 JAR 文件。main
最后,用你的方法传递类的完整包名。
例如,对于 JAR 文件中的应用程序,该应用程序在名为的包中命名为类中my_app.jar
的方法,以及同一文件夹中的一些所需 jar:main
App
com.example
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:.
希望有帮助!
您需要单独添加它们。或者,如果您真的只需要指定一个目录,您可以将所有内容解压缩到一个目录中并将其添加到您的类路径中。但是,我不推荐这种方法,因为您可能会在类路径版本控制和不可管理性方面出现奇怪的问题。
将 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”。
我在一个文件夹中有多个罐子。下面的命令对我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 和当前目录的类文件的方式设置类路径。
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
命令的参数顺序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