从命令提示符中执行具有多个类路径库的jar文件

65

我有一个使用Maven构建的项目,它生成一个jar文件并将所有依赖项复制到target/lib文件夹中。我想在客户端的机器(Windows)上执行此项目。因此,我将myproject.jar复制到C:\xyz文件夹中,将所有依赖项复制到C:\xyz\lib文件夹中。如何从客户端命令提示符中执行此项目?

我尝试在C:\xyz文件夹中使用java -cp lib\*.jar -jar myproject.jar,但会抛出以下错误。

Exception in thread "main" java.lang.NoClassDefFoundError: lib\commons-codec-1/3/jar
Caused by: java.lang.ClassNotFoundException: lib\commons-codec-1.3.jar
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: lib\commons-codec-1.3.jar.  Program will exit.

我认为如果在类路径中指定所有依赖项(例如java -cp lib\dep1.jar;dep2.jar),它将摆脱问题,但我不想这样做,因为我已经有40个库了,并且它可能会在未来版本中增加。 有更好的方法吗?

9个回答

81
您不能同时使用-jar-cp命令 - 参见Java文档,如果您使用-jar

JAR文件是所有用户类的来源,其他用户类路径设置将被忽略。

您可以这样做:

java -cp lib\*.jar;. myproject.MainClass

注意在-cp参数中有;.,以解决Java命令行中的一个bug。另请注意,这是Windows版本的命令。Unix中的路径分隔符为:


1
从我在文档中阅读的内容来看,* 代表一个或多个 jar 文件。因此,您需要使用 -cp lib*; 的方式进行说明。您不应该按照正常意义(一个或多个字符)使用它。 - Brian
1
实际上,*.jar 对我来说不起作用(在树莓派上运行)。 - bvdb
当本应让你的生活更轻松的工具反而带来更多麻烦时... - Ahmadov
我只想补充一下,这在 PowerShell 中目前不起作用,但在命令提示符中可以正常工作... - Amnestic
2
真遗憾的是,-cp-jar不能同时使用。我有一个需要用户提供JDBC库才能正常使用的CLI程序,在将其打包为可执行的JAR文件时会遇到一些挑战。 - Christopher Schultz

68

在UNIX系统上使用Java 1.7 -

java -cp myjar.jar:lib/*:. mypackage.MyClass
在 Windows 上,您需要使用 ';' 而不是 ':' -
java -cp myjar.jar;lib/*;. mypackage.MyClass

我已经找了30分钟了,试图在树莓派上运行一个应用程序。结果发现我只需要将“;”分隔符替换为“:”即可。谢谢 :) - bvdb
谢谢。这对我有用。Windows 版本的。 - Coder17

15

让Maven生成一个批处理文件来启动您的应用程序,这是最简单的方法。

您可以使用appassembler-maven-plugin插件进行此类操作。


当您使用 -jar 时,-cp 将被忽略。另一方面,'-cp lib/*.jar' 和 '-cp lib/dep1.jar;lib/dep2.jar...' 是相同的,我认为这是从 Java1.5 开始的。 - Michael Chen

12
无论操作系统如何,下面的命令都应该能够工作:
java -cp "MyJar.jar;lib/*" com.mainClass

请始终使用引号,并注意lib / *.jar将无法正常工作。


实际上,根据操作系统的不同,命令也有所不同。在Windows中应该使用分号,在Unix中应该使用冒号。 - Evelino Bomitali

3
您可以使用maven-assembly-plugin插件,以下是来自官方网站的示例: https://maven.apache.org/plugins/maven-assembly-plugin/usage.html
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
                <manifest>
                    <mainClass>your main class</mainClass>
                </manifest>
            </archive>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id> <!-- this is used for inheritance merges -->
                <phase>package</phase> <!-- bind to the packaging phase -->
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

2
一个可能的解决方案是:
创建一个批处理文件,在其中对 lib 目录中的所有文件进行循环,并将 lib 中的每个文件设置在 classpath 上。
然后在执行 jar 文件之前运行该批处理文件。
有关循环的信息,请参阅批处理文件中的 for 循环。来源:http://www.robvanderwoude.com/for.php

1
我遇到了同样的问题,但是通过使用Maven Shade Plugin将所有依赖项打包到我的jar文件中解决了这个问题。

1

有几个选项可供选择。

最简单的可能是exec插件

您还可以使用assembly插件生成包含所有依赖项的jar文件。

最后,您可以使用dependency:classpath目标生成一个包含类路径的文件。


我们的客户在他们的机器上没有安装Maven。抱歉,我应该提到这一点。 - Praneeth
我可以使用汇编插件,但无法使用执行插件。 - Praneeth

-2

这个命令不起作用:java -cp lib\*.jar -jar myproject.jar。你必须一个一个地把它放进去。

所以,在commons-codec-1.3.jar的情况下。

java -cp lib/commons-codec-1.3.jar;lib/next_jar.jar等等。

另一个解决方案可能是将所有JAR文件放入JRE的ext目录中。如果您使用独立的JRE,则可以这样做。如果您正在使用相同的JRE来运行多个应用程序,则我不建议这样做。


2
通配符类路径可在JDK 6+中使用,问题在于您不能同时指定-jar-cp。将您的jar文件放置在扩展目录中,我个人认为是一个相当糟糕的主意。 - Dave Newton
@DaveNewton 是的,这个问题是关于执行带有其依赖项的jar文件。 - Jagger
是的,你可以使用通配符类路径来实现。填充扩展目录会影响你运行的所有内容,如果你运行任何其他内容,这是很危险的。这是一个Maven项目,请使用Maven。 - Dave Newton
@DaveNewton 你想如何实现呢?放置通配符,然后放置包含 main 方法的类的完全限定名?拥有一个可执行的 jar 文件的整个思路是为了避免在执行时放置完全限定名,而是将其放在清单文件中。 - Jagger
1
如果你认为“笨重”意味着“可能会破坏世界上的一切”,那当然可以。 - Dave Newton
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接