将所有jar包含在Java类路径中的目录中

Chr*_*rra 968 java command-line classpath

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

我正在尝试java -classpath lib/*.jar:. my.package.Program,它无法找到肯定在那些罐子里的类文件.我是否需要将每个jar文件分别添加到类路径中?

bas*_*ero 1113

使用Java 6或更高版本,classpath选项支持通配符.请注意以下事项:

  • 使用直引号(")
  • 使用*,而不是*.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 ' ' ':')

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

了解通配符

Classpath文档:

类路径条目可以包含基本名称通配符*,该字符被认为等同于指定具有扩展名.jar或目录的目录中的所有文件的列表.JAR.例如,类路径条目foo/*指定名为foo的目录中的所有JAR文件.一个只包含的类路径条目*扩展为当前目录中所有jar文件的列表.

包含的类路径条目*与类文件不匹配.要在单个目录foo中匹配类和JAR文件,请使用 foo;foo/*foo/*;foo.选择的顺序确定是否foo在JAR文件之前加载类和资源,foo反之亦然.

不会递归搜索子目录.例如,foo/*仅在查找JAR文件foo,而不是在foo/bar,foo/baz

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

在类加载过程本身期间,在调用程序的main方法之前,而不是迟到,扩展通配符是在早期完成的.包含通配符的输入类路径的每个元素都由枚举命名目录中的JAR文件生成的(可能为空)元素序列替换.例如,如果目录foo包含a.jar,b.jarc.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

  • 也不要在-cp中使用`~` (3认同)
  • 该特征记录很少,并且似乎需要满足一些不太明显的前提条件才能按预期工作. (2认同)
  • 我有一个没有任何引号的命令 `java -classpath /jars/*:/anotherJarsDir/* com.test.MyClass`,它工作正常。我想知道为什么 shell 没有扩展它并出错? (2认同)

dav*_*orp 221

在Windows下,这工作:

java -cp "Test.jar;lib/*" my.package.MainClass
Run Code Online (Sandbox Code Playgroud)

这不起作用:

java -cp "Test.jar;lib/*.jar" my.package.MainClass
Run Code Online (Sandbox Code Playgroud)

注意*.jar,所以*通配符应该单独使用.


在Linux上,以下工作:

java -cp "Test.jar:lib/*" my.package.MainClass
Run Code Online (Sandbox Code Playgroud)

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

  • 完美的答案.需要注意的两件重要事项:1)使用引号和2)仅使用*,而不是*.jar (17认同)
  • 一年零8个月之后,我所做的编辑包括UNIX版本再次保存了我.:)有趣的是如何用`*.jar`识别我的jar文件,但只能用`*`. (4认同)
  • 第三个例子适用于Linux(Ubuntu 12.04 LTS). (3认同)
  • @SebastianGodelet - 是的,这只是我在正则表达式通配符和这个符号之间感到困惑,我猜这不一样。大多数情况下,拯救我的是了解一个平台上的 `:` 和另一个平台上的 `;` 之间的区别。:) 我大约每年从命令行用 Java 编译一次,足以让我不记得是多少次,但频率却足以令人烦恼。 (2认同)

oxb*_*kes 65

我们通过部署一个 jar文件解决了这个问题,该文件myapp.jar包含一个manifest(Manifest.mf)文件,该文件指定了一个带有其他所需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
Run Code Online (Sandbox Code Playgroud)

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

  • oxbow_lakes的答案并不完全正确; 如果你用java -jar myapp.jar启动这个jar,那么Class-Path的东西很荣幸(并且只有被尊重; -cp/-classpath被忽略!).我认为oxbow_lakes的意思是当他写'java -classpath myapp.jar'时写的. (6认同)

Hab*_*abi 46

我的解决方案在Ubuntu 10.04上使用java-sun 1.6.0_24,所有jar都在"lib"目录中:

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

如果失败,则以下命令应该有效(将lib目录中的所有*.jars打印到classpath参数)

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

  • 一个有趣的笔记.java -cp lib/*my.main.Class总是失败因为lib/*的shell glob扩展,而java -cp.:lib/*my.main.Class不会因为.:lib/*不是有效的glob路径.花点时间注意一下 (4认同)

Pop*_*ops 35

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

Oracle提供了有关在类路径中使用通配符的文档,这些通配符用于Java 6,此处用于Java 7,在标题" 理解类路径通配符 "一节中.(在我写这篇文章时,这两个页面包含相同的信息.)以下是重点摘要:

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

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

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

  • 通配符不会在子目录中搜索JAR.

  • 如果使用CLASSPATH系统属性-cp-classpath命令行标志,则上述要点为true .但是,如果使用Class-PathJAR清单标头(就像使用ant构建文件一样),则不会遵循通配符.

是的,我的第一个链接与得分最高的答案中提供的链接相同(我没有超车的希望),但这个答案并没有提供超出链接的解释.由于这些天 Stack Upflow 不鼓励这种行为,我想我会扩展它.


SAN*_*NN3 34

对我来说,这适用于Windows.

java -cp "/lib/*;" sample
Run Code Online (Sandbox Code Playgroud)

对于Linux

java -cp "/lib/*:" sample
Run Code Online (Sandbox Code Playgroud)

我使用的是Java 6


Wen*_*der 30

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

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

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


Nav*_*avi 27

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

运行java时外部jar的目录

  • java.ext.dirs与classpath中的普通jar有很大的不同.它具有更高的优先级和权限,可以以某种方式覆盖bootstamp中的类(rt.jar) (5认同)
  • 这可行,但请注意,传递`-Djava.ext.dirs =`BEFORE` -jar` (3认同)

rve*_*ica 22

正确:

java -classpath "lib/*:." my.package.Program
Run Code Online (Sandbox Code Playgroud)

不正确:

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
Run Code Online (Sandbox Code Playgroud)


小智 9

如果您确实需要动态指定所有.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>
Run Code Online (Sandbox Code Playgroud)

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


小智 9

如果您使用的是Java 6,则可以在类路径中使用通配符.

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

javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.java  -d build/classes
Run Code Online (Sandbox Code Playgroud)

参考:http://www.rekk.de/bloggy/2008/add-all-jars-in-a-directory-to-classpath-with-java-se-6-using-wildcards/


Jak*_*nto 8

请注意,Windows上的Java 7通配符扩展已中断.

有关更多信息,请查看此StackOverflow问题.

解决方法是在通配符后面加上分号. java -cp "somewhere/*;"


Evg*_*eev 6

敬启者,

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

作品:

$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.java
Run Code Online (Sandbox Code Playgroud)

不起作用:

$ 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
Run Code Online (Sandbox Code Playgroud)

我很确定shell不会扩展通配符,因为例如

$ echo './*'
./*
Run Code Online (Sandbox Code Playgroud)

(尝试使用其他程序,而不是内置程序,echo结果相同.)

我相信它javac正试图扩展它,并且无论论证中是否有分号,它的行为都不同.首先,它可能试图扩展看起来像路径的所有参数.只有这样它才能解析它们,-cp只需要使用以下标记.(注意那com.comsol.aco_1.0.0.jar是该目录中的第二个JAR.)这都是猜测.

这是

$ javac -version
javac 1.7.0
Run Code Online (Sandbox Code Playgroud)


rea*_*lPK 5

如果您在Eclipse或Netbeans之类的任何IDE之外开发和运行Java应用程序,那么上述所有解决方案都将非常有用。

如果您使用的是Windows 7并且使用Java的Eclipse IDE进行开发,则在使用命令提示符运行Eclipse内置的类文件时,可能会遇到问题。

例如,您在Eclipse中的源代码具有以下程序包层次结构:edu.sjsu.myapp.Main.java

您将json.jar作为Main.java的外部依赖项

当您尝试从Eclipse中运行Main.java时,它将正常运行。

但是,当您在Eclipse中编译Main.java之后尝试使用命令提示符运行此命令时,它将发出一些奇怪的错误,提示“ ClassNotDef错误等等”。

我假设您在源代码的工作目录中!

使用以下语法从命令提示符运行它:

  1. javac -cp “。; json.jar” Main.java

  2. java -cp “。; json.jar” edu.sjsu.myapp.Main

    [不要错过。以上]

这是因为您已将Main.java放在edu.sjsu.myapp包中,而java.exe会查找确切的模式。

希望能帮助到你 !!


Bas*_*que 5

macOS,当前文件夹

\n\n

对于macOS Mojave上的 Java 13 \xe2\x80\xa6

\n\n

如果您的所有.jar文件都位于同一文件夹中,请使用cd使其成为您的当前工​​作目录。验证与pwd.

\n\n

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

\n\n

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

\n\n
java -classpath my_app.jar:* com.example.App\n
Run Code Online (Sandbox Code Playgroud)\n


Dan*_*wak 3

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

  • 这可能是 08 年回归的唯一途径,但现在不再是了。 (3认同)