java -jar命令运行jar包时指定外部依赖jar包

本文介绍了Java应用项目打包成jar文件的方法及如何正确引用第三方jar包。提供了四种解决jar包引用问题的方案,并详细说明了每种方法的操作步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个jar包的程序入口。具体的方法是修改jar包内目录META-INF下的MANIFEST.MF文件。比如有个叫做test.jar的jar包,里面有一个拥有main函数的main class:test.someClassName。我们就只要在MANIFEST.MF里面添加如下一句话:

Main-Class: test.someClassName

然后我们可以在控制台里输入java -jar test.jar即可以运行这个jar。但是我们这个项目需要引用其他第三方的jar包,在eclipse里面以项目jar包的形式引用了这个叫做some.jar的包,当时放在项目的lib子目录下,最后项目打包时把这个some.jar也打进来了,但是用java -jar执行这个test.jar的时候报找不到Class异常,原因就是jar引用不到放在自己内部的jar包。那怎么办?运行时将其加入classpath的方式行不行?就是在运行jar的同时加入classpath参数:

java -classpath some.jar -jar test.jar

这种方式是不行的,因为使用classpath指定的jar是由AppClassloader来加载,java命令加了-jar 参数以后,AppClassloader就只关注test.jar范围内的class了,classpath参数失效。那该怎么引用其他的jar包呢?

方法一、使用Bootstrap Classloader来加载这些类

我们可以在运行时使用如下参数:

-Xbootclasspath:完全取代系统Java classpath.最好不用。
-Xbootclasspath/a: 在系统class加载后加载。一般用这个。
-Xbootclasspath/p: 在系统class加载前加载,注意使用,和系统类冲突就不好了.

win32 java -Xbootclasspath/a: some.jar;some2.jar; -jar test.jar

unix    java -Xbootclasspath/a: some.jar:some2.jar: -jar test.jar

win32系统每个jar用分号隔开,unix系统下用冒号隔开

 

方法二、使用Extension Classloader来加载

首先介绍下java.ext.dirs参数的使用和环境变量:java中系统属性java.ext.dirs指定的目录由ExtClassLoader加载器加载,如果您的程序没有指定该系统属性(-Djava.ext.dirs=sss/lib)那么该加载器默认加载$JAVA_HOME/lib/ext目录下的所有jar文件。但如果你手动指定系统属性且忘了把$JAVA_HOME/lib/ext路径给加上,那么ExtClassLoader不会去加载$JAVA_HOME/lib/ext下面的jar文件,这意味着你将失去一些功能,例如java自带的加解密算法实现。

在一个小项目中,出于简化需要,没有划分不同的模块,而是视为一个模块,打成一个jar包,通过java -cp 类名的方式进行不同的调用。因为引用的jar包比较多,所以使用了java.ext.dirs进行简化处理。为了保证java自身的ext jar包引用,需要在java.ext.dirs中增加相应路径。命令行如下:

java -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:/project/script/ -cp /project/script/ -Dlog4j.configuration=file:/project/script/log4j.properties com.galaxy.Comments 洛阳 /project/out/

这样,在 /project/script/中的所有jar文件都会自动加入到classpath中,该命令在shell模式中运行正常。

或者你可以把需要加载的jar都扔到%JRE_HOME%/lib/ext下面,这个目录下的jar包会在Bootstrap Classloader工作完后由Extension Classloader来加载。非常方便,非常省心。:)

java -cp命令介绍

java -cp .;c:\dir1\lib.jar Test

-cp和-classpath 一样,是指定类运行所依赖其他类的路径,通常是类库,jar包之类,需要全路径到jar包,window上";"分隔,linux上是":"分隔。不支持通配符,需要列出所有jar包,用"."代表当前路径。虽然现在都有eclipse之类的IDE了,但有时候后会手工编译和运行一些程序,很多人包括多年开发经验的人都不知道怎么在命令行参数运行类。 

使用范例: 
java -cp ..\lib\hsqldb.jar org.hsqldb.Server -database mydb   或  
java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 mydb -dbname.0 mydb  

java -jar minusyhd.jar  
Manifest-Version: 1.0  
Main-Class: minusyhd.MinusYHD  
Class-Path: jconn4.jar 

-cp 参数后面是类路径,是指定给解释器到哪里找到你的.class文件, 写法:

java -cp .;myClass.jar packname.mainclassname

classpath中的jar文件能使用通配符,如果是多个jar文件,要一个一个地罗列出来,从某种意义上说jar文件也就是路径。
要指定各个JAR文件具体的存放路径,相同路径有多个可使用通配符
java -cp .;c:\classes\myClass.jar;d:\classes\*.jar packname.mainclassname

bat文件写法:

java -cp MinusYHD.jar minusyhd.MinusYHD > minusyhed.log  
exit

注:"> minusyhed.log" 指定System.out输出文件名
 

Reference:Classpath - Wikipedia --- 类路径 - 维基百科

方法三、还是用AppClassloader来加载,不过不需要classpath参数了

我们在MANIFEST.MF中添加如下代码:

Class-Path: lib/some.jar

lib是和test.jar同目录的一个子目录,test.jar要引用的some.jar包就在这里面。然后测试运行,一切正常!

如果有多个jar包需要引用的情况:

Class-Path: lib/some.jar lib/some2.jar

每个单独的jar用空格隔开就可以了。注意使用相对路径。

另:如果META-INF 下包含INDEX.LIST文件的话,可能会使Class-Path配置失效。INDEX.LIST是Jar打包工具打包时生成的索引文件,删除对运行不产生影响。

方法四、自定义Classloader来加载

这种方法是终极解决方案,基本上那些知名java应用都是那么干的,如tomcat、jboss等等。

这种方式有点复杂,需要专门开贴讨论。关于ClassLoader的原理和自定义ClassLoader可以参考这篇http://cuixiaodong214.blog.163.com/blog/static/951639820099135859761

总结:

以上四种方法都可以用,特别是程序运行在非常单纯的环境中时。但是,如果是运行在多任务,多应用的环境中时,最好每个应用都能相互独立,第一种和第二种方案都有可能对其他应用产生影响,因此最好就是选择第三种和第四种。

参考:

java命令执行jar包的方式

java -cp 命令介绍

jar命令图解

### 通过 `java -jar` 命令指定 main 方法运行 jar 要使用 `java -jar` 命令运行一个 jar ,必须确保该 jar 含正确的 MANIFEST.MF 文件,并在其中指定了 `Main-Class` 属性。以下是实现这一目标的详细方法: #### 配置 MANIFEST.MF 文件 MANIFEST.MF 文件位于 JAR 文件的 `META-INF` 目录下,用于定义 JAR 文件的元数据。为了使 `java -jar` 命令能够正确运行,必须在 MANIFEST.MF 文件中指定 `Main-Class` 属性,例如: ```plaintext Manifest-Version: 1.0 Main-Class: com.example.MainClass ``` 上述配置表明,当运行JAR 文件,将调用 `com.example.MainClass` 中的 main 方法[^2]。 #### 使用 Maven 打指定 main 方法 如果项目使用 Maven 构建工具,可以通过 `maven-jar-plugin` 或 `maven-assembly-plugin` 插件来指定 main 方法。以下是一个示例配置,展示如何在 `pom.xml` 文件中设置 main 类: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <mainClass>com.mypackage.MainClass</mainClass> </manifest> </archive> </configuration> </plugin> ``` 上述配置会在生成的 JAR 文件中自动添加正确的 MANIFEST.MF 文件,指定 `com.mypackage.MainClass` 作为主类[^4]。 #### 使用 IntelliJ IDEA 打指定 main 方法 对于非 Maven 项目,可以使用 IntelliJ IDEA 的 Artifact 功能来打 JAR 文件并指定 main 方法。具体步骤如下: 1. 进入 `File -> Project Structure -> Artifacts`。 2. 点击加号按钮,选择 `JAR -> From modules with dependencies`。 3. 在弹出的窗口中选择含目标 main 方法的模块,并指定 main 类。 4. 完成配置后,点击 `Build -> Build Artifacts` 来生成 JAR 文件[^2]。 #### 运行生成的 JAR 文件 生成的 JAR 文件可以通过以下命令运行: ```bash java -jar your-application.jar ``` 如果需要传递参数给 main 方法,可以在命令后附加参数,例如: ```bash java -jar your-application.jar arg1 arg2 ``` 或者通过系统属性传递参数: ```bash java -Dparam1=value1 -Dparam2=value2 -jar your-application.jar ``` #### 注意事项 - 如果 MANIFEST.MF 文件未正确配置或缺少 `Main-Class` 属性,则运行会报错 `Error: Could not find or load main class`[^5]。 - 对于依赖项的项目,建议使用 `maven-assembly-plugin` 插件生成带有所有依赖项的可执行 JAR 文件[^3]。 ### 示例代码结构 假设项目的代码结构如下: ```plaintext src/ ├── com/ │ └── example/ │ └── MainClass.java // 含 main 方法的类 resources/ ├── application.properties // 配置文件 lib/ ├── dependency1.jar // 外部依赖 ``` #### 配置后的 MANIFEST.MF 文件内容示例 ```plaintext Manifest-Version: 1.0 Main-Class: com.example.MainClass ``` ###
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值