java -jar与java -cp
通常情况下,我们会看到以下两种命令启动的Java程序:
shell
java -jar xxx.jar [args]
java -cp xxx.jar mainclass [args]
这两种用法有什么区别呢?
1、情景描述
1)Java打包单个类
例如,在com.test
下有一个文件Hello.java
,在test
目录CMD命令行下执行编译:
bash
javac Hello.java
在com
上层目录CMD命令行执行单个类打jar
包命令:
bash
java -cvf test.jar com
2)分别执行java -jar和java -cp
执行java -jar
命令:
bash
java -jar test.jar Tom
# test.jar中没有主清单属性
执行java -cp
命令:
bash
java -cp test.jar com.test.Hello Tom
# Hello Tom
也就是java -jar
命令执行报错,java -cp
命令执行成功。这是什么原因呢?
2、情景分析
首先jar
包实际上和zip
压缩文件是一样的,我们甚至完全可以用zip
压缩工具来压缩com
目录,然后用java -cp com.zip com.test.Hello Tom
运行。不同的是,使用java
命令打出的jar
包会多出来一个东西:META-INF
目录
该目录里面有一个MANIFEST.MF
文件,这个文件就是jar
的主清单文件。java -jar
提示"没有主清单属性",就是因为主清单文件中缺失了一个属性:Main-Class
,它声明了jar
包的默认入口类,也就是java -jar
运行时开始执行的类,其格式为:
bash
Main-Class: com.test.Hello
如果我们在MANIFEST.MF
文件中添加上述属性,java -jar
将执行成功。需要注意的是,该属性冒号后面有一个空格,且属性结束必须换行
当然,在打jar
包时可以通过-e
参数指定默认入口类(自动生成Main-Class
属性),在com
上层目录CMD命令行执行单个类打jar
包命令:
bash
java -cvfe test.jar com.test.Hello com
执行java -jar
命令:
bash
java -jar test.jar Tom
# Hello Tom
3、两者区别
使用java -jar
运行jar
包时,虚拟机将忽略系统中的classpath
配置,如果有依赖jar
,需要在主清单属性中指定,格式为:
bash
Class-Path: xx01.jar xx02.jar org/xx03.jar
多个jar
包之间使用空格隔开,其路径是相对于当前运行jar
包所在的目录
使用java -cp
运行jar
包时,cp
本身就是classpath
的意思,依赖多个jar
时,直接在命令中指定,格式为:
bash
java -cp test.jar;xx01.jar;xx02.jar com.test.Hello
值得注意的是,多个jar
包之间的分隔符在Windows上是;
,而在Linux中是:
综上所述,java -jar
命令与java -cp
命令的区别总结如下:
-
java -jar :用来执行可执行
jar
,其可执行性由jar
包中的主清单属性Main-Class
决定 -
java -cp :纯粹的
java
命令,在指定classpath
下查找Java类文件并执行,使用更灵活
参考文章:https://blog.csdn.net/firstendhappy/article/details/119209167