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

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

相关文章

  • Java class文件格式之属性详解_动力节点java学院整理

    Java class文件格式之属性详解_动力节点java学院整理

    这篇文章主要介绍了Java class文件格式之属性详解,需要的朋友可以参考下
    2017-06-06
  • 详解使用spring boot admin监控spring cloud应用程序

    详解使用spring boot admin监控spring cloud应用程序

    本篇文章主要介绍了详解使用spring boot admin监控spring cloud应用程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Spring Bean创建和循环依赖

    Spring Bean创建和循环依赖

    这篇文章主要介绍了Spring Bean创建和循环依赖,讲述了Spring容器中 Bean 的创建过程已经主要的方法,另外也着重分析了循环依赖的问题,需要的小伙伴可以参考一下
    2022-05-05
  • 关于Java中修饰符的总结(fina除外)

    关于Java中修饰符的总结(fina除外)

    下面小编就为大家带来一篇关于Java中修饰符的总结(fina除外)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • Java Cache详解及简单实现

    Java Cache详解及简单实现

    这篇文章主要介绍了 Java Cache详解及简单实现的相关资料,需要的朋友可以参考下
    2017-02-02
  • Java基于Lock的生产者消费者模型示例

    Java基于Lock的生产者消费者模型示例

    这篇文章主要介绍了Java基于Lock的生产者消费者模型,结合实例形式分析了java基于锁机制的生产者消费者模型相关实现与使用技巧,需要的朋友可以参考下
    2018-08-08
  • Java常见的四种负载均衡算法

    Java常见的四种负载均衡算法

    本文主要介绍了Java常见的四种负载均衡算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • JVM完全解读之YGC来龙去脉分析

    JVM完全解读之YGC来龙去脉分析

    YGC是JVM GC当前最为频繁的一种GC,一个高并发的服务在运行期间,会进行大量的YGC,发生YGC时,会进行STW,一般时间都很短,除非碰到YGC时,存在大量的存活对象需要进行拷贝
    2022-01-01
  • 关于spring 扫描不到jar中class文件的原因分析及解决

    关于spring 扫描不到jar中class文件的原因分析及解决

    这篇文章主要介绍了关于spring 扫描不到jar中class文件的原因分析及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java中的同步与异步详细介绍

    Java中的同步与异步详细介绍

    这篇文章主要介绍了Java中的同步与异步详细介绍,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11

最新评论