包括Java类路径中一个目录中的所有jar

有没有办法将所有jar文件包含在类路径的目录中?

我正在尝试java -classpath lib/*.jar:. my.package.Program,但无法找到肯定在这些jar中的类文件。我需要将每个jar文件单独添加到类路径吗?

1219944 次浏览

您需要单独添加它们。或者,如果您真的只需要指定一个目录,您可以将所有内容unjar到一个目录中并将其添加到您的类路径中。但是,我不推荐这种方法,因为您可能会在类路径版本控制和不可管理性方面遇到奇怪的问题。

将jar文件视为目录结构的根目录。是的,您需要单独添加它们。

如果您真的需要动态指定所有. jar文件,您可以使用shell脚本或apacheant。有一个名为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>

在您的启动构建文件中,它将使用正确的类路径启动您的应用程序。

我们通过部署一个主要 jar文件myapp.jar来解决这个问题,该文件包含一个清单Manifest.mf)文件,该文件指定了一个类路径和其他所需的jar,然后将其部署在一起。在这种情况下,您只需在运行代码时声明java -jar myapp.jar

因此,如果您将mainjar部署到某个目录中,然后将依赖的jar放入该目录下的lib文件夹中,清单如下所示:

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

注意:这是独立于平台的-我们可以使用相同的jar在UNIX服务器或Windows PC上启动。

使用Java6或更高版本,类路径选项支持通配符。

  • 使用直接引号("
  • 使用*,而不是*.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 "$(printf %s: lib/*.jar)"

(请注意,使用类路径与-jar选项不兼容。另请参阅:从命令提示符执行具有多个类路径库的jar文件

理解通配符

来自类路径文档:

类路径条目可以包含basename通配符*,它被认为等同于指定所有文件的列表在扩展名为.jar.JAR的目录中。例如,类路径条目foo/*指定名为foo。仅由*组成的类路径条目扩展为所有当前目录中的jar文件。

包含*的类路径条目将不匹配类文件。到在单个目录foo中匹配类和JAR文件,使用foo;foo/*foo/*;foo。选择的顺序决定了foo中的类和资源在foo中的JAR文件之前加载,或者反之亦然

子目录不会递归搜索。例如,foo/*看起来对于仅在foo中的JAR文件,不在foo/barfoo/baz等中。

目录中JAR文件的枚举顺序未指定扩展类路径,可能因平台而异平台,甚至在同一台机器上时时刻刻。A构造良好的应用程序不应依赖于任何特定的顺序。如果需要特定的顺序,则JAR文件可以是在类路径中显式枚举。

通配符的扩展很早就完成了,在调用程序的main方法,而不是在类加载期间延迟进程本身。输入类路径的每个元素都包含一个通配符被元素序列(可能为空)替换通过枚举命名目录中的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中已知的bug,windows示例必须在条目前面使用反斜杠,后面加上星号:https://bugs.openjdk.java.net/browse/JDK-8131329

我知道的唯一方法是单独做,例如:

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

希望有帮助!

在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

分隔符是冒号而不是分号

对于Windows,需要引号和;应用作分隔符。例如:

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

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

运行java时外部jar的目录

如果使用Java6,则可以在类路径中使用通配符。

现在可以在类路径定义中使用通配符:

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/

我在Ubuntu 10.04上使用java-sun 1.6的解决方案。0_24将所有jar放在“lib”目录中:

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

If this fails, the following command should work (prints out all *.jars in lib directory to the classpath param)

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

如果您在任何IDE(如Eclipse或NetBeans)之外开发和运行Java应用程序,上述所有解决方案都非常有效。

如果您使用的是Windows 7并在Java中使用了Eclipse IDE for Development,那么如果使用命令提示符运行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.myappjava.exe将查找确切的模式。

希望有帮助!!!

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

Oracle在标题理解类路径通配符下提供了在类路径6Java7Java中使用通配符的留档。(在我撰写本文时,这两个页面包含相同的信息。)

  • 一般来说,要包含给定目录中的所有JAR,您可以使用通配符*not*.jar)。

  • 通配符只匹配JAR,不匹配类文件;要获取目录中的所有类,只需在目录名处结束类路径条目。

  • 上述两个选项可以组合在一起以包含目录中的所有JAR和类文件,并且适用通常的类路径优先级规则。例如。-cp /classes;/jars/*

  • 通配符将在子目录中搜索JAR。

  • 如果您使用CLASSPATH系统属性或-cp-classpath命令行标志,上述要点是正确的。但是,如果您使用Class-Path JAR清单标头(就像您可能对ant构建文件所做的那样),通配符将被尊重。

是的,我的第一个链接与得分最高的答案(我没有超越的希望)中提供的链接相同,但是这个答案并没有提供链接之外的太多解释。由于这种行为是不鼓励的在Stack Overflow上,这些天

正确

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

错误:

java -classpath "lib/a*.jar:." my.package.Programjava -classpath "lib/a*:."     my.package.Programjava -classpath "lib/*.jar:."  my.package.Programjava -classpath  lib/*:.       my.package.Program

对我来说,这适用于Windows。

java -cp "/lib/*;" sample

对于linux

java -cp "/lib/*:" sample

我正在使用Java6

简体:如果你的main在jar中,你可能需要一个额外的'-jar path To/your Jar/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肯定是坏的),然而,在我使用的一个罐子中,我发现了方便的“jarinjar”技巧的中断,Eclipse在选择该选项时利用了这个技巧。即使在意识到我需要opt3,然后找到这个StackOverflow条目之后,我仍然花了一些时间来弄清楚如何在Eclipse之外启动我的main,所以这是对我有用的,因为它对其他人有用…


如果你给罐子命名:"fooBarTheJarFile.jar"并全部设置为导出到目录:“/theFully/QuatifiedPath/toYourChosenDir”。

(这意味着“导出目的地”字段将读作:“/theFully/QuatifiedPath/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'是声明的包路径,您将在'TheClassWithYourMain.java'文件的顶部找到,该文件包含您希望从Java外部运行的'main(String[]args){…}')


需要注意的缺陷是:在您声明的类路径上的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.TheClassWithYourMainBREAKS:  java -cp ".;fooBarTheJarFile_lib/*"                              package.path_to.the_class_with.your_main.TheClassWithYourMainBREAKS:  java -cp ".;fooBarTheJarFile_lib/*"   -jar                       package.path_to.the_class_with.your_main.TheClassWithYourMainWORKS:   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上,Java7的通配符扩展被破坏。

查看这个StackOverflow问题以获取更多信息。

解决方法是在通配符后面放一个分号。java -cp "somewhere/*;"

它可能与谁有关,

我在MSYS/MinGW shell下的Windows上发现了这种奇怪的行为。

作品:

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

不工作:

$ javac -cp 'c:\Programs\COMSOL44\plugins\*' Reclaim.javajavac: invalid flag: c:\Programs\COMSOL44\plugins\com.comsol.aco_1.0.0.jarUsage: 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 -versionjavac 1.7.0

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

这不是将/*设置为-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;

如果提供了适当的目录作为“libDir2Scan4jars”的输入;脚本将扫描所有的jar并创建一个类路径字符串并将其导出到环境变量“tmpCLASSPATH”。

以适合多个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

windows
#请求参数

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

Linux
#请求参数

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

提醒:
-windows路径分隔符是;
-Linux路径分隔符是:
-在Windows中,如果cp参数不包含空格,则“引号”是可选的

我在一个文件夹中有多个jar。下面的命令在JDK1.8中为我工作,以包含文件夹中存在的所有jar。请注意,如果您在类路径中有空格,请包含在引号中

windows

编译: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

macOS,当前文件夹

Java13macOS mojave

如果您的所有.jar文件都在同一个文件夹中,请使用#1使其成为您的当前工作目录。使用#2进行验证。

对于-classpath,您必须首先列出应用程序的JAR文件。使用冒号字符:作为分隔符,附加星号*以获取同一文件夹中的所有其他JAR文件。最后,使用#3方法传递类的完整包名。

例如,对于名为my_app.jar的JAR文件中的应用程序,在名为com.example的包中名为App的类中的main方法,以及同一文件夹中的一些所需的jar:

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

java命令的参数顺序也很重要:

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

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