文章目录
负一、运行环境与前置要求
- 使用
Linux
环境; - 安装了
JDK
(Java Development Kit);
注:由于后面用到的 jar
工具是 JDK
的一部分,如果只安装了 JRE
而没有安装 JDK
的话可能会没有该工具。
零、编写并编译 java 源代码文件
如果懒得看中间的内容,建议看完 “零、编写并编译 java 源代码文件” 后直接跳到 “四、整体流程”。
编写 java 源代码文件
例如,当前 java 文件名为 “Hello.java”,该文件中有一个主类 Hello
,包声明为 testproject.hello
,源代码如下:
package testproject.hello;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
编译 java 源代码文件
在 Hello.java
所在的目录运行一个命令提示符 或 Shell
,在终端输入如下命令:
javac -d . Hello.java
其中 -d
参数指明在何处安置文件树,例如 -d .
表示将编译得到的文件树,安置在当前目录下。如果不使用 -d
参数,java 编译器也可以正确地生成 Hello.class
文件,但是并不会创建文件树,而是直接在当前目录创建 Hello.class
文件。正确的文件树结构是 java 项目能够生成可执行 jar 包的必要条件。
编译后生成的文件树结构如下:
└─testproject
└─hello
Hello.class
可以看到, Hello.class
类文件被安置在了目录 testproject/hello
中。同理,java 源代码中定义的每一个类在编译后都会得到一个 .class
文件,他们会被安置在 package
声明对应的文件树中。
一、编写 MANIFEST.MF 文件
MANIFEST.MF 的基本格式如下。
Manifest-Version: 1.0
Created-By: 作者
Main-Class: 入口类
这里的入口类不仅要指出类名,还要包含这个类的包的名字,例如上述项目,我们可以这样编写 MANIFEST 文件。
Manifest-Version: 1.0
Created-By: GGN_2015
Main-Class: testproject.hello.Hello
方便起见,我们把 MANIFEST.MF 它放在了当前目录。
需要注意的是 MANIFEST 文件末尾必须要有一个空行,而且每行的冒号后面必须要有一个空格。
注:如果忘记了文件末尾的空行,打包操作能够正确进行,但是这样得到的 jar
包在运行时会产生一个错误:no main manifest attribute, in 文件名.jar
。如果冒号后忘记了空格,会在生成 jar
包时产生一个运行时错误:java.io.IOException: invalid header field
。
二、将编译得到的 .class 文件进行打包
使用 MANIFEST 文件打包
在终端输入如下命令进行打包:
jar cvfm 目标文件名.jar MANIFEST.MF <被打包的class文件序列>
注:此时必须保证 .class
文件均位于自己正确的文件树结构中,否则打包得到的 .jar
文件将无法运行。
例如上面的例子中我们可以使用如下的编译命令:
jar cvfm Hello.jar MANIFEST.MF ./testproject/hello/Hello.class
执行此命令后,当前目录下生成了一个名为 Hello.jar
的文件,如果有很多 .class
文件要被加入到文件序列中,可以使用 *.class
或者 *.*
等带通配符的文件名。
使用自动生成的 MANIFEST 文件打包
还有一种不用自己创建 MANIFEST
文件的打包方式:
jar cvfe Hello.jar 入口类 <被打包的class文件序列>
这里的 “入口类” 也要给出完整的包名,格式和 MANIFET 文件中要求相同。通过这种方式打包无需自己创建 MANIFEST 文件,编译得到的 .jar
中会根据这个入口类自动创建一个 MANIFEST 文件。
三、执行 .jar 文件
使用如下命令即可执行一个有 MANIFEST
文件的 .jar
文件。
java -jar 文件名.jar
例如,在上面的例子中我们可以这样运行 Hello.jar
:
java -jar Hello.jar
四、整体流程
打包时使用自动生成的 MANIFEST 文件,编译与打包命令大致结构如下:
javac -d . *.java # 编译当前目录下的所有 .java 文件
jar cvfe 文件名.jar 入口类名 包路径/*.class
java -jar 文件名.jar # 运行 jar 包
示例:
javac -d . Hello.java
jar cvfe Hello.jar testproject.hello.Hello testproject/hello/Hello.class
java -jar Hello.jar