Ja va 开发者日常打包和运行程序时,总会遇到两个最常见的命令:ja va -cp 和 ja va -jar。它们到底有什么区别?什么时候该用哪个?这里把经验拆开讲透。

ja va -cp(或 ja va -classpath)
这个选项的作用是告诉 JVM:去哪儿找依赖的 jar 包和主类。路径必须写绝对路径,多个 jar 之间在 Linux 下用冒号(:)分隔,Windows 下用分号(;)分隔。当然,全称 -classpath 也行,而且支持通配符 *,省得一个一个写。
基本格式:
ja va -cp .;myClass.jar packagename.mainclassname
举个例子:
ja va -cp .;c:/classes/myClass.jar;d:/classes/*.jar packagename.mainclassname
或者更实际一点的 Spark 场景:
ja va -cp D:\spark\spark-2.3.3\assembly\target\scala-2.11\jars\* org.apache.spark.deploy.master.Master
注意,classpath 里用通配符 * 时可以匹配所有 jar。而最后那个 packagename.mainclassname 就是包含 main 方法的完全限定类名。如果 classpath 中有多个类都有 main 方法,用 -cp 可以灵活指定入口。
有一个关键点容易被忽略:一旦用了 -jar 选项,-cp、-classpath 以及环境变量 CLASSPATH 都会被 JVM 直接忽略。也就是说,-jar 和 -cp 互斥,不可同时生效。
ja va -jar
这个命令用于直接运行一个可执行的 jar 包。它依赖打包时生成的 META-INF/MANIFEST.MF 文件,其中 Main-Class 属性指定了主类。运行后不能再额外指定其他依赖 jar——所有依赖必须在打包时一并包含。
基本格式:
ja va -jar myClass.jar
实际路径示例:
ja va -jar E:\workspace\idmapping\target\idmapping-1.0-SNAPSHOT.jar
指定 main-class 的两种方式
方式一:Ma ven 打包时在 pom.xml 中配置
在 pom.xml 的 里指定主类,例如:
org.apache.ma ven.plugins
ma ven-compiler-plugin
1.8
1.8
org.apache.ma ven.plugins
ma ven-assembly-plugin
packagename.mainclassname
jar-with-dependencies
make-assemble
package
single
方式二:直接在 MANIFEST.MF 中指定
在 META-INF/MANIFEST.MF 文件里写入:
Manifest-Version: 1.0
Main-Class: packagename.mainclassname
实际场景总结
用 Ma ven 导出的 jar 包,如果打包时没把依赖打进去,那么打出的包并不包含依赖库,运行时可能会报 ClassNotFoundException。这时候就需要根据情况选择命令:
- 如果打包时指定了主类,直接
ja va -jar xxx.jar即可。 - 如果打包时没有指定主类,可以用
ja va -cp xxx.jar 主类全名来运行。 - 如果需要引用额外的 jar 包,可以用
ja va -classpath $CLASSPATH:xxxx.jar 主类全名,其中-classpath指定需要引入的类路径。
掌握这几个场景,项目中遇到启动问题就能快速定位——是路径没写对,还是主类没指定,还是依赖没打包进去。这些细节往往是新手最头疼的地方,也是老手一眼就能看穿的坑。