当前位置:首页 > 后端开发 > 正文

java 怎么打jar包

先用 javac 编译源码生成 .class 文件,再用 jar cvf yourapp.jar -C [编译输出目录] . 打包, yourapp.jar 替换为你的目标 J

核心概念前置

JAR(Java ARchive)本质是 ZIP 格式压缩包,除存储 .class 文件外,还可封装资源文件、配置文件及元数据,其核心功能包括:
代码分发载体
可执行程序容器(需定义入口点)
多模块整合方案
第三方库交付标准

注意:普通 JAR 仅含编译后的字节码,若需直接运行需显式声明主类;若未声明则视为纯类库。


基础打包流程(命令行版)

场景 1:基础打包(无主类)

适用于纯类库开发,仅需将编译产物打包。

# 切换至项目根目录(含 src/main/java 结构)
cd /path/to/project
# 1. 创建临时编译目录
mkdir -p build/classes
# 2. 编译源码(自动生成包路径)
javac -d build/classes src/main/java//.java
# 3. 打包为 JAR(不含主类)
jar cvf my-library.jar -C build/classes .

参数解析
| 参数 | 作用 | 示例值 |
|——|——|——–|
| c | 创建新归档 | — |
| v | 显示处理过程 | — |
| f | 指定输出文件名 | my-library.jar |
| -C | 切换工作目录 | build/classes |
| | 打包当前目录下所有内容 | — |

场景 2:可执行 JAR(含主类)

适用于独立应用开发,需指定程序入口。

# 1. 编译阶段同上
javac -d build/classes src/main/java//.java
# 2. 创建带 Manifest 的 JAR
jar cvfe my-app.jar com.example.MainClass -C build/classes .

关键差异

  • e 参数:指定主类全限定名(如 com.example.MainClass
  • 自动生成 META-INF/MANIFEST.MFMain-Class 属性决定可执行入口

验证执行

java -jar my-app.jar  # 无需指定主类

主流 IDE 操作指南

Eclipse 实现步骤

  1. 导出向导File → Export → Java → Runnable JAR file
  2. 关键配置项
    • Launch configuration:选择已有启动配置
    • Export destination:输出路径及文件名
    • Library handling:建议选 “Package required libraries into generated JAR”(自动打包依赖)
  3. 生成结果:包含所有依赖的胖 JAR(Fat JAR)

IntelliJ IDEA 实现步骤

  1. 菜单路径Build → Build Artifacts...
  2. 新建 Artifact:选择 JAR → From modules with dependencies
  3. 核心配置
    • Main Class:手动输入或通过浏览选择
    • Output directory:指定输出路径
    • Include in project build:勾选以加入构建流程
  4. 高级选项:可通过 “Before packaging” 添加预处理脚本

Manifest 文件深度解析

META-INF/MANIFEST.MF 是 JAR 的核心元数据文件,典型结构如下:

Manifest-Version: 1.0
Main-Class: com.example.MainClass  ; 程序入口(必需)
Class-Path: lib/mysql-connector.jar ; 外部依赖路径(可选)
Sealed: true                        ; 禁止修改内容(安全校验)

常用属性说明
| 属性 | 作用 | 示例 |
|——|——|——|
| Main-Class | 指定可执行主类 | com.example.App |
| Class-Path | 外部依赖相对路径 | lib/gson-2.8.6.jar |
| Sealed | 启用数字签名验证 | true |
| Permissions | 安全策略配置 | all-permissions |

特殊场景处理

  • 多模块系统:通过 Class-Path 引用兄弟模块 JAR
  • 动态加载资源:将图片/配置文件放在 JAR 内部,通过 getResourceAsStream() 读取
  • 跨平台兼容性:确保换行符统一为 n(Unix 风格)

构建工具集成方案

Maven 标准实践

pom.xml 关键配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

执行命令mvn clean package

Gradle 灵活配置

build.gradle 示例:

jar {
    manifest {
        attributes(
            'Main-Class': 'com.example.MainClass',
            'Implementation-Title': 'My Application',
            'Implementation-Version': version
        )
    }
    from sourceSets.main.output // 自动包含编译输出
}

执行命令gradle build


高级技巧与注意事项

胖 JAR(Fat JAR)制作

解决依赖管理痛点,将所有依赖合并到一个 JAR:

  • Maven Shade Plugin
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.example.MainClass</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
  • 注意事项:可能导致类冲突,建议使用唯一前缀重命名包(如 @obfuscate

资源文件打包

将非 Java 文件(如 HTML/CSS/properties)纳入 JAR:

# 命令行方式
jar cvf my-app.jar -C src/main/resources .

目录结构建议:遵循 Maven 标准布局,资源放 src/main/resources,编译后自动进入 JAR 根目录。

版本控制与签名

  • 版本标识:在 Manifest 中添加 Implementation-Version 属性
  • 数字签名:使用 jarsigner 工具进行 GPG/PKCS#12 签名,增强安全性
    jarsigner -keystore mykeystore.jks -storepass changeit my-app.jar myalias

相关问答 FAQs

Q1: 为什么我的 JAR 文件双击打不开?

A:可能原因及解决方案:

  1. 缺少主类声明:检查 Manifest 中是否存在 Main-Class 属性,且类名完全匹配(区分大小写)。
  2. 路径错误:若使用 Class-Path 引用外部 JAR,需确保相对路径正确(相对于主 JAR 的位置)。
  3. JDK 版本不兼容:确认编译使用的 JDK 版本与运行时环境一致(如用 Java 8 编译的 JAR 不能在 Java 7 运行)。
  4. 权限问题:Windows 系统下需检查文件关联是否正确,建议通过命令行 java -jar yourfile.jar 测试。

Q2: 如何让 JAR 包含所有依赖库?

A:推荐以下三种方案:

  1. 构建工具自动打包:使用 Maven Shade Plugin 或 Gradle shadow plugin 生成胖 JAR。
  2. 手动指定 Class-Path:在 Manifest 中添加 Class-Path: lib/dependency.jar,并将依赖放在同级 lib 目录。
  3. Uberjar/Superjar:通过 OneJar 等第三方工具合并所有依赖,但需注意类冲突问题。

归纳对比表

维度 命令行原生方式 Maven/Gradle IDE 导出
灵活性 (完全控制) (受限于插件) (图形化限制)
依赖管理 需手动处理 自动解析依赖树 可视化选择依赖
跨平台性 强(纯命令行) 强(脚本化) 依赖 IDE 安装包
学习成本 高(需熟悉参数) 中(需掌握 DSL) 低(向导式操作)
适用场景 小型项目/定制需求 中大型项目/持续集成
JAR
0