将Java类path中的所有jar包括在一个目录中

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

我正在尝试java -classpath lib/*.jar:. my.package.Program java -classpath lib/*.jar:. my.package.Program ,它无法find当然在这些jar子里的类文件。 我是否需要将每个jar文件分别添加到类path中?

使用Java 6或更高版本,类path选项支持通配符。 请注意以下几点:

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

视窗

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 ' ' ':')

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

了解通配符

从Classpath文件:

类path条目可以包含基本名称通配符* ,这被认为等价于指定扩展名为.jar.JAR的目录中所有文件的列表。 例如,类path条目foo/*指定名为foo的目录中的所有JAR文件。 一个由*组成的类path条目将展开为当前目录中所有jar文件的列表。

包含*类path条目将不匹配类文件。 要在单个目录foo中匹配类和JAR文件,请使用foo;foo/*foo/*;foo 。 所select的顺序决定foo中的类和资源是否在foo中的JAR文件之前被加载,反之亦然。

子目录不会被recursionsearch。 例如, foo/*仅在foo查找JAR文件,而不是在foo/barfoo/baz等中

目录中的JAR文件在扩展类path中枚举的顺序没有指定,并且可能因平台而异,甚至在同一台机器上不一样。 一个构造良好的应用程序不应该依赖于任何特定的顺序。 如果需要特定的顺序,那么可以在类path中显式枚举JAR文件。

扩展通配符是在调用程序的主要方法之前提早完成的,而不是在类加载过程本身的晚期。 包含通配符的input类path的每个元素都被通过枚举指定目录中的JAR文件生成的(可能为空)元素序列replace。 例如,如果目录foo包含a.jarb.jarc.jar ,那么类pathfoo/*被扩展到foo/a.jar;foo/b.jar;foo/c.jar和该string将是系统属性java.class.path的值。

CLASSPATH环境variables的处理方式与-classpath (或-cp )命令行选项不同。 也就是说,通配符在所有这些情况下都很荣幸​​。 但是,类path通配符在Class-Path jar-manifest头文件中不受尊重。

在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 

分隔符是冒号而不是分号。

我们通过部署一个包含清单Manifest.mf )文件的 jar文件myapp.jar来解决这个问题,该文件指定了一个类path和其他所需的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 

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

我在Ubuntu 10.04上使用java-sun 1.6.0_24在“lib”目录下有所有jar的解决scheme:

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

如果失败了,下面的命令应该可以工作(将lib目录中的所有* .jar打印到classpath参数中)

  java -cp $(对于我在lib / *。jar;执行echo -n $ i:; done)。  my.main.Class 

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

Oracle在这里为Java 6和Java 7提供了在类path中使用通配符的文档,在标题为“ 理解类path通配符 ”一节中。 (当我写这个时,这两个页面包含相同的信息。)下面是亮点摘要:

  • 通常,要将所有JAR包含在给定的目录中,可以使用通配符*不是 *.jar )。

  • 通配符只匹配JAR,而不是类文件; 要获取目录中的所有类,只需在目录名称处结束类path条目即可。

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

  • 通配符不会在子目录中searchJAR。

  • 如果您使用CLASSPATH系统属性或-cp-classpath命令行标志,上述项目符号为真。 但是,如果使用Class-Path JAR清单头文件(就像你使用ant构build文件所做的那样),通配符将不会被使用。

是的,我的第一个链接是在得分最高的答案(我不希望超车)中提供的第一个链接,但是这个答案没有提供超出链接的解释。 由于这种行为在堆栈溢出这些天 不鼓励 ,我想我会扩展它。

对我来说这在Windows中工作。

 java -cp "/lib/*;" sample 

对于Linux

 java -cp "/lib/*:" sample 

我正在使用Java 6

正确

 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 -Djava.ext.dirs=jarDirectory http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html

运行java时外部jar的目录

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

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

提醒:
Windowspath分隔符是“ ;
Linuxpath分隔符是“
– 在Windows中,如果cp参数不包含空格,则“引号”是可选的

如果您确实需要dynamic指定所有.jar文件,则可以使用shell脚本或Apache Ant 。 有一个名为Commons Launcher的公共项目,它基本上可以让你指定你的启动脚本作为一个ant构build文件(如果你明白我的意思)。

然后,你可以指定类似于:

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

在您的启动构build文件,这将启动您的应用程序与正确的类path。

如果您使用Java 6,则可以在类path中使用通配符。

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

 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/*;"

致相关人士,

我在MSYS / MinGWshell的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正在试图扩大它,它的行为不同,是否有分号的论点或不。 首先,它可能试图扩大看起来像path的所有论据。 只有它才会parsing它们,而-cp只取下面的标记。 (请注意, com.comsol.aco_1.0.0.jar是该目录中的第二个JAR。)这全是猜测。

这是

 $ javac -version javac 1.7.0 

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

如果您使用的是Windows 7并使用Eclipse IDE进行Java开发,那么如果使用命令提示符运行Eclipse中构build的类文件,则可能会遇到问题。

例如,您在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将查找确切的模式。

希望它有帮助!

对于窗户报价是必需的, 应该用作分隔符。 例如:

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

简短forms:如果你的main是在一个jar文件中,你可能需要另外一个明确声明的“-jar pathTo / yourJar / YourJarsName.jar”来使它工作(即使'YourJarsName.jar'在类path中)(或者,expression回答了5年前提出的原始问题:你不需要明确地重新声明每个jar,但看起来,即使使用java6,你也需要重新声明自己的jar …)


长forms:(我已经明确指出,我希望即使是java的入侵者也可以利用这个)

像许多这里我使用Eclipse来导出jar子:(文件 – >导出 – >“可运行的JAR文件”)。 “图书馆处理”日食(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子中的本地代码,我发现与select该选项时,日食使用的方便的“jarinjar”技巧会中断。 即使意识到我需要opt3,然后find这个StackOverflow条目,但仍然花了我一些时间来弄清楚如何在eclipse之外启动我的主体,所以这里是对我有用的,因为它对其他人很有用。


如果你命名你的jar:“fooBarTheJarFile.jar”,并且全部设置为导出到dir:“/ 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'是声明的包path,你可以在'TheClassWithYourMain.java'文件的顶部find包含'main(String [] args) 。}你希望从java之外运行)


需要注意的是:在声明的类path中的jar列表中有'fooBarTheJarFile.jar'是不够的。 您需要显式声明'-jar',并重新声明该jar的位置。

例如,这打破了:

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

用相对path重新表示:

 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位服务器虚拟机)

我知道如何单独做这件事的唯一方法,例如:

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

希望有所帮助!

不是一个直接的解决scheme,可以设置/ *到-cp,但我希望你可以使用下面的脚本缓解dynamic类path和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脚本,也可以有一个类似的窗口。 如果提供了正确的目录作为“libDir2Scan4jars”的input; 该脚本将扫描所有的jar并创build一个classpathstring并将其导出到一个envvariables“tmpCLASSPATH”。

你需要分别添加它们。 或者,如果您确实需要指定一个目录,则可以将所有内容解压缩到一个目录中,然后将其添加到您的类path中。 我不推荐使用这种方法,因为在类path版本化和不可pipe理性方面存在一些奇怪的问题。

把一个jar文件想象成一个目录结构的根。 是的,你需要分别添加它们。

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

以适合多个jar和当前目录的类文件的方式设置classpath。

 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