将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/bar
,foo/baz
等中目录中的JAR文件在扩展类path中枚举的顺序没有指定,并且可能因平台而异,甚至在同一台机器上不一样。 一个构造良好的应用程序不应该依赖于任何特定的顺序。 如果需要特定的顺序,那么可以在类path中显式枚举JAR文件。
扩展通配符是在调用程序的主要方法之前提早完成的,而不是在类加载过程本身的晚期。 包含通配符的input类path的每个元素都被通过枚举指定目录中的JAR文件生成的(可能为空)元素序列replace。 例如,如果目录
foo
包含a.jar
,b.jar
和c.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”。
我假设你在你的源代码的工作目录!
使用以下语法从命令提示符运行它:
-
javac -cp “。; json.jar” Main.java
-
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