Java JAR文件的打包与运行过程
作者:面朝大海,春不暖,花不开
在 Java 开发中,JAR(Java Archive)文件是一种核心的分发格式,用于将多个类文件、元数据和资源打包成一个压缩文件。JAR 文件不仅便于应用程序的部署,还可以通过配置清单文件(manifest)使其成为可执行文件。本文将深入探讨如何使用 JDK 的 jar 工具手动创建 JAR 文件,以及如何利用 Maven 自动化这一过程。我们将通过清晰的示例和步骤,确保内容深入浅出,为技术人员提供实用的指导。
本文的目标是帮助您:
- 理解 JAR 文件的作用和结构。
- 掌握使用
jar工具创建可执行 JAR 文件的方法。 - 学习如何配置 Maven 以生成包含依赖的 JAR 文件。
- 了解高级工具(如
jpackage)的潜在用途。
什么是 JAR 文件?
JAR 文件是基于 ZIP 和 ZLIB 压缩格式的归档文件,主要用于打包 Java 应用程序或库的组件,包括:
- 类文件:编译后的
.class文件,包含 Java 程序的字节码。 - 资源文件:如图片、配置文件或音频文件。
- 清单文件:位于
META-INF/MANIFEST.MF,包含文件的元数据和属性。
JAR 文件的主要优势包括:
- 高效分发:将所有相关文件打包为单一文件,便于传输。
- 压缩:减少文件大小,加快下载速度。
- 可执行性:通过指定
Main-Class属性,JAR 文件可以直接运行。 - 模块化:自 JDK 9 起,JAR 文件支持模块化打包(模块化 JAR)。
使用 jar 命令创建 JAR 文件
JDK 提供的 jar 工具是创建和操作 JAR 文件的标准工具。以下是通过命令行创建可执行 JAR 文件的步骤。
步骤 1:编写并编译 Java 代码
假设我们有一个简单的 Java 程序 HelloWorld.java,位于 com.somedomainhere 包中:
package com.somedomainhere;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World of Java");
}
}在命令行中,编译该文件:
javac com/somedomainhere/HelloWorld.java
这将在 com/somedomainhere 目录下生成 HelloWorld.class 文件。
步骤 2:创建清单文件
要使 JAR 文件可执行,需要一个清单文件来指定主类。创建一个名为 manifest.stub 的文本文件,内容如下:
Main-Class: com.somedomainhere.HelloWorld
注意:
Main-Class属性区分大小写,且冒号后必须有一个空格。- 文件必须以换行符结尾,否则可能导致解析错误。
步骤 3:创建 JAR 文件
假设当前目录结构如下:
.
└── com
└── somedomainhere
└── HelloWorld.class在包含 com 目录的根目录下,运行以下命令:
jar cvmf manifest.stub hello.jar com/somedomainhere/HelloWorld.class
命令参数说明:
c:创建新的归档文件。v:显示详细输出(verbose)。m:包含指定的清单文件(manifest.stub)。f:指定输出文件名(hello.jar)。
执行后,将生成 hello.jar,其中包含正确的包结构(com/somedomainhere/HelloWorld.class)和清单文件。
步骤 4:验证 JAR 文件内容
您可以使用以下命令查看 JAR 文件的内容:
jar tf hello.jar
输出示例:
META-INF/
META-INF/MANIFEST.MF
com/
com/somedomainhere/
com/somedomainhere/HelloWorld.class
运行 JAR 文件
创建 JAR 文件后,可以通过以下命令运行:
java -jar hello.jar
java -jar 命令会读取清单文件中的 Main-Class 属性,并执行指定的主类。运行上述命令将输出:
Hello, World of Java
在支持的 GUI 平台(如 Windows、macOS 或某些 Linux 桌面环境)上,您可以双击 JAR 文件运行,前提是系统已将 .jar 文件关联到 Java 运行时环境(JRE)。
注意:
- 确保已安装 Java 运行时环境(JRE)或 JDK。
- 如果 JAR 文件缺少
Main-Class属性或主类不存在,将抛出异常。
使用 Maven 创建 JAR 文件
对于大型项目,手动创建 JAR 文件可能效率低下。Maven 是一种流行的构建工具,可以自动化编译、打包和依赖管理。以下是如何使用 Maven 创建可执行 JAR 文件的步骤。
步骤 1:设置 Maven 项目
创建一个标准的 Maven 项目,目录结构如下:
hello-world/
├── pom.xml
└── src
└── main
└── java
└── com
└── somedomainhere
└── HelloWorld.javaHelloWorld.java 的内容与之前相同。
步骤 2:配置 pom.xml
在 pom.xml 中,指定项目的基本信息和插件配置。以下是一个基本的配置,用于生成可执行 JAR 文件:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.somedomainhere</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.somedomainhere.HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>说明:
<packaging>jar</packaging>:指定项目打包为 JAR 文件。maven-compiler-plugin:设置 Java 编译版本(这里使用 Java 8)。maven-jar-plugin:配置清单文件,指定主类。
运行以下命令生成 JAR 文件:
mvn clean package
这将在 target 目录下生成 hello-world-1.0-SNAPSHOT.jar。您可以运行:
java -jar target/hello-world-1.0-SNAPSHOT.jar
步骤 3:包含依赖项(创建胖 JAR)
如果您的项目有外部依赖(如第三方库),上述 JAR 文件不包含这些依赖,运行时可能抛出 ClassNotFoundException。要创建包含所有依赖的“胖 JAR”,可以使用 maven-assembly-plugin。
在 pom.xml 中添加以下插件配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.somedomainhere.HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>运行以下命令:
mvn clean package
这将生成两个 JAR 文件:
target/hello-world-1.0-SNAPSHOT.jar:不包含依赖的普通 JAR。target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar:包含所有依赖的胖 JAR。
运行胖 JAR:
java -jar target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar
优点:
- 胖 JAR 是自包含的,可以在任何安装了 Java 的环境中运行,无需额外配置类路径。
- 便于分发,适合独立应用程序。
注意:
- 胖 JAR 可能显著增加文件大小,因为它包含所有依赖。
- 确保依赖的许可证允许这种打包方式。
示例:添加依赖
假设您的程序使用 Apache Commons Lang 库。更新 pom.xml 添加依赖:
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>修改 HelloWorld.java 使用该库:
package com.somedomainhere;
import org.apache.commons.lang3.StringUtils;
public class HelloWorld {
public static void main(String[] args) {
String message = "hello, world of java";
System.out.println(StringUtils.capitalize(message));
}
}重新运行 mvn clean package,生成的胖 JAR 将包含 Commons Lang 库,运行时将输出:
Hello, world of java
高级主题
使用 Maven Shade 插件
虽然 maven-assembly-plugin 适用于大多数场景,但 maven-shade-plugin 提供了更高级的功能,如包重命名(shading)以避免类冲突。配置示例:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.somedomainhere.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>运行 mvn clean package 将生成包含所有依赖的 JAR 文件。Shade 插件特别适合需要处理复杂依赖冲突的项目。
使用 jpackage 工具
自 Java 14 起,JDK 引入了 jpackage 工具,可创建平台特定的安装程序(如 Windows 的 .exe 或 macOS 的 .dmg)。它将应用程序和 JRE 打包在一起,适合分发给非技术用户。
示例命令:
jpackage --input target --name HelloWorld --main-jar hello-world-1.0-SNAPSHOT.jar --main-class com.somedomainhere.HelloWorld
由于 jpackage 超出了 JAR 文件的范围,建议有兴趣的读者参考 Oracle 文档。
常见问题与注意事项
| 问题 | 解决方案 |
|---|---|
| java -jar 抛出 no main manifest attribute | 确保清单文件中包含 Main-Class 属性,或在 jar 命令中使用 -e 选项指定主类。 |
| 运行胖 JAR 时出现 ClassNotFoundException | 确认 maven-assembly-plugin 已正确配置,且所有依赖都包含在 JAR 中。 |
| JAR 文件过大 | 考虑使用普通 JAR 并通过类路径管理依赖,或检查是否有不必要的依赖。 |
| 双击 JAR 文件无法运行 | 确保系统安装了 JRE,并将 .jar 文件关联到 javaw.exe。 |
总结
打包和运行 JAR 文件是 Java 开发中的核心技能。通过 jar 工具,您可以手动创建简单的 JAR 文件,适合小型项目或学习目的。而 Maven 提供了强大的自动化功能,能够处理复杂的依赖管理和构建流程,使其成为现代 Java 开发的首选工具。本文通过详细的示例和配置,展示了从基础到高级的 JAR 文件管理方法。
无论您是初学者还是经验丰富的开发者,掌握这些技术将显著提高您的开发效率。建议进一步探索 Maven 的其他插件(如 maven-shade-plugin)或 jpackage 工具,以满足更复杂的部署需求。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
