仅通过命令行与MANIFEST编译运行含JAR依赖的Java程序方法
解决JavaTuples依赖缺失的命令行编译打包全流程
先把你的目录结构理清楚(方便后续操作):
. ├── com # 你的源码包目录 │ └── directoryA │ └── ... # 嵌套子目录,存放所有.java文件 ├── lib # 依赖库目录 │ └── javatuples-1.2.jar ├── META-INF # 自定义MANIFEST目录 │ └── MANIFEST.MF └── target # 空目录,用来存编译后的class文件
第一步:编译Java源码(带依赖)
编译时必须把JavaTuples的JAR包加入编译路径,否则编译器找不到org.javatuples.Pair这类依赖类。在根目录下执行这条命令:
javac -d target -cp lib/javatuples-1.2.jar com/**/*.java
简单解释:
-d target:把编译生成的class文件统一放到target目录,自动保留原有的包结构(比如com/directoryA/xxx.class)-cp lib/javatuples-1.2.jar:指定编译依赖的类路径,包含JavaTuples的JAR包com/**/*.java:匹配com目录下所有子目录里的.java源文件(如果你的shell不支持**,可以换成find com -name "*.java"来批量指定源文件)
第二步:编写正确的MANIFEST.MF
MANIFEST必须包含两个关键项:主类的全限定名,以及依赖库的路径。打开META-INF/MANIFEST.MF,写入以下内容(注意最后一行必须是空行,否则会失效):
Manifest-Version: 1.0 Main-Class: com.directoryA.YourMainClass # 替换成你实际的主类全限定名,比如com.example.Main Class-Path: lib/javatuples-1.2.jar
重点注意:
Class-Path里的路径是相对于最终生成的JAR包的位置,因为你的lib目录和根目录同级,所以写成lib/javatuples-1.2.jar就对了- 主类名一定要写全,包括完整的包名,否则运行时找不到程序入口
第三步:打包带MANIFEST的可执行JAR
在根目录下执行打包命令,把target里的class文件和META-INF里的MANIFEST一起打包:
jar cvfm your-app.jar META-INF/MANIFEST.MF -C target/ .
命令解释:
cvfm:c=创建新JAR,v=显示打包过程,f=指定JAR文件名,m=指定自定义MANIFEST文件-C target/ .:进入target目录,把里面的所有内容(包结构和class文件)加入JAR包
第四步:运行可执行JAR
确保your-app.jar和lib目录在同一级(也就是根目录下),然后执行:
java -jar your-app.jar
这样运行时JVM会根据MANIFEST里的Class-Path自动加载lib里的JavaTuples JAR,就不会再抛出NoClassDefFoundError了。
至于IntelliJ能正常运行的原因:IDE会自动把lib里的JAR加入到运行时的类路径里,而命令行下需要我们手动指定编译和运行时的类路径,或者通过MANIFEST来配置。
内容的提问来源于stack exchange,提问作者matthew_t_smith
相关产品推荐
相关产品推荐

