Java JAR文件的打包与运行过程

 更新时间:2025年05月01日 10:55:34   作者:面朝大海,春不暖,花不开  
这篇文章主要介绍了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.java

HelloWorld.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 工具,以满足更复杂的部署需求。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot中Redis的缓存更新策略详解

    SpringBoot中Redis的缓存更新策略详解

    这篇文章主要介绍了SpringBoot中Redis的缓存更新策略,缓存一般是为了应对高并发场景、缓解数据库读写压力,而将数据存储在读写更快的某种存储介质中(如内存),以加快读取数据的速度,需要的朋友可以参考下
    2023-08-08
  • spring framework体系结构及模块jar依赖关系详解

    spring framework体系结构及模块jar依赖关系详解

    在本篇文章里小编给大家整理的是关于spring framework体系结构及模块jar依赖关系,对此有兴趣的朋友们可以学习下。
    2019-09-09
  • java sqlserver text 类型字段读取方法

    java sqlserver text 类型字段读取方法

    有这样一个需求,需要将原本存储在数据库中的文档转存至文件系统中,于是写了一个简单的程序完成此功能
    2012-11-11
  • SpringBoot ApplicationEvent之事件发布与监听机制详解

    SpringBoot ApplicationEvent之事件发布与监听机制详解

    本文将深入探讨SpringBoot的事件机制,介绍其核心概念、实现方法及最佳实践,帮助开发者构建更加灵活、可维护的应用架构,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Spring Boot两种全局配置和两种注解的操作方法

    Spring Boot两种全局配置和两种注解的操作方法

    Spring Boot使用一个application.properties或者application.yaml的文件作为全局配置文件,本文重点给大家介绍Spring Boot两种全局配置和两种注解的配置方法,感兴趣的朋友一起看看吧
    2021-06-06
  • java查找图中两点之间所有路径

    java查找图中两点之间所有路径

    这篇文章主要为大家详细介绍了java查找图中两点之间所有路径,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Java spring注解@PostConstruct实战案例讲解

    Java spring注解@PostConstruct实战案例讲解

    我们在Spring项目中经常会遇到@PostConstruct注解,可能有的伙伴对这个注解很陌生,下面这篇文章主要给大家介绍了关于Java spring注解@PostConstruct实战案例讲解的相关资料,需要的朋友可以参考下
    2023-12-12
  • 详解Spring Security的formLogin登录认证模式

    详解Spring Security的formLogin登录认证模式

    对于一个完整的应用系统,与登录验证相关的页面都是高度定制化的,非常美观而且提供多种登录方式。这就需要Spring Security支持我们自己定制登录页面,也就是本文给大家介绍的formLogin模式登录认证模式,感兴趣的朋友跟随小编一起看看吧
    2019-11-11
  • Java程序运行时出现乱码问题的排查与解决方法

    Java程序运行时出现乱码问题的排查与解决方法

    本文主要介绍了Java程序运行时出现乱码问题的排查与解决方法,包括检查Java源文件编码、检查编译时的编码设置、检查运行时的编码设置、检查命令提示符的代码页、检查命令提示符的字体、检查 Java 程序的输出代码以及检查环境变量,需要的朋友可以参考下
    2025-03-03
  • GitLab在IDEA中回滚主分支问题

    GitLab在IDEA中回滚主分支问题

    这是工作中遇到的问题,记录下来,也方便自己后面查看操作步骤,也方便各位遇到这个问题,不至于卡太久,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11

最新评论