java中jar包运行之-jar和-cp命令
或多或少,我们都会见到用这两种命令启动java程序,最基本的用法如:
java [options] -jar xxx.jar [args]
java [options] -cp xxx.jar classname [args]
那这两种用法有什么区别呢?
我们先写一个简单的测试类(为了方便说明问题,不借助开发工具):
1)在本机随便找个目录,创建com.test目录,并编写HelloTest.java文件:
package com.test;
public class HelloTest {
public static void main(String[] args) {
String name = args[0];
System.out.println("hello:"+name);
}
}
2)编译:
3)打jar包:
4)我们尝试用最开始说的两种命令来执行
发现-jar命令执行的结果提示:没有主清单属性,什么意思呢?
首先说下jar包,jar包跟我们通常认知的.zip压缩文件,是一样一样的,我们甚至完全可以用普通zip压缩工具来压缩com目录,然后用java -cp com.zip com.test.HelloTest everybody照样能运行,不同的是,用jar命令打出的jar包会多出来一个东西:
看到没,一个META-INF目录,里面有一个文件:MANIFEST.MF,其内容如下:
Manifest-Version: 1.0
Created-By: 1.8.0_171 (Oracle Corporation)
这个文件就是jar的清单文件,可以理解成一个标识配置文件,上面说的java -jar执行结果提示:没有主清单属性,就是因为我们的清单文件中少了一样属性,这个属性是:Main-Class,它声明了jar包的默认入口类,也是java -jar运行时开始执行的类,其格式为:
Main-Class: com.test.HelloTest
我们把test.jar解压后,在MANIFEST.MF文件中加入该属性:
然后用.zip格式直接再次压缩后(命名为test2.jar),执行java -jar test2.jar
注意:清单属性配置格式问题,冒号后面需要一个空格,否则会报Error: Invalid or corrupt jarfile错误,属性结束必须换行,否则仍然找不到属性
当然,实际上也不需要如此麻烦,我们在打jar包时可以通过-e参数指定默认入口,会自动生成Main-Class属性,此时jar包就是一个可执行jar文件:
用java -jar运行jar包时,虚拟机忽略系统中的classpath配置,如果有依赖jar,需要在清单属性中指定,格式为:
Class-Path: servlet.jar infobus.jar acme/beans.jar
多个jar包之间用空格隔开,其位置是相对于当前运行的jar包所在的目录;
用java -cp运行时,其cp本身就是classpath的意思,对于多个依赖的jar格式为:
java -cp test.jar;test1.jar;test2.jar com.test.HelloTest
注意:jar包之间的分隔符在windows上是分号";",而在linux中是冒号":"。
综上所述:
java -jar用来执行可执行jar包,其可执行的特性,由jar包中的清单属性Main-Class决定;
java -cp命令是纯粹的java命令,在指定的classpath中查找java类文件并执行,使用更灵活;