Java?JAR文件的打包與運(yùn)行過程
在 Java 開發(fā)中,JAR(Java Archive)文件是一種核心的分發(fā)格式,用于將多個(gè)類文件、元數(shù)據(jù)和資源打包成一個(gè)壓縮文件。JAR 文件不僅便于應(yīng)用程序的部署,還可以通過配置清單文件(manifest)使其成為可執(zhí)行文件。本文將深入探討如何使用 JDK 的 jar 工具手動(dòng)創(chuàng)建 JAR 文件,以及如何利用 Maven 自動(dòng)化這一過程。我們將通過清晰的示例和步驟,確保內(nèi)容深入淺出,為技術(shù)人員提供實(shí)用的指導(dǎo)。
本文的目標(biāo)是幫助您:
- 理解 JAR 文件的作用和結(jié)構(gòu)。
- 掌握使用
jar工具創(chuàng)建可執(zhí)行 JAR 文件的方法。 - 學(xué)習(xí)如何配置 Maven 以生成包含依賴的 JAR 文件。
- 了解高級(jí)工具(如
jpackage)的潛在用途。
什么是 JAR 文件?
JAR 文件是基于 ZIP 和 ZLIB 壓縮格式的歸檔文件,主要用于打包 Java 應(yīng)用程序或庫(kù)的組件,包括:
- 類文件:編譯后的
.class文件,包含 Java 程序的字節(jié)碼。 - 資源文件:如圖片、配置文件或音頻文件。
- 清單文件:位于
META-INF/MANIFEST.MF,包含文件的元數(shù)據(jù)和屬性。
JAR 文件的主要優(yōu)勢(shì)包括:
- 高效分發(fā):將所有相關(guān)文件打包為單一文件,便于傳輸。
- 壓縮:減少文件大小,加快下載速度。
- 可執(zhí)行性:通過指定
Main-Class屬性,JAR 文件可以直接運(yùn)行。 - 模塊化:自 JDK 9 起,JAR 文件支持模塊化打包(模塊化 JAR)。
使用 jar 命令創(chuàng)建 JAR 文件
JDK 提供的 jar 工具是創(chuàng)建和操作 JAR 文件的標(biāo)準(zhǔn)工具。以下是通過命令行創(chuàng)建可執(zhí)行 JAR 文件的步驟。
步驟 1:編寫并編譯 Java 代碼
假設(shè)我們有一個(gè)簡(jiǎn)單的 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:創(chuàng)建清單文件
要使 JAR 文件可執(zhí)行,需要一個(gè)清單文件來指定主類。創(chuàng)建一個(gè)名為 manifest.stub 的文本文件,內(nèi)容如下:
Main-Class: com.somedomainhere.HelloWorld
注意:
Main-Class屬性區(qū)分大小寫,且冒號(hào)后必須有一個(gè)空格。- 文件必須以換行符結(jié)尾,否則可能導(dǎo)致解析錯(cuò)誤。
步驟 3:創(chuàng)建 JAR 文件
假設(shè)當(dāng)前目錄結(jié)構(gòu)如下:
.
└── com
└── somedomainhere
└── HelloWorld.class在包含 com 目錄的根目錄下,運(yùn)行以下命令:
jar cvmf manifest.stub hello.jar com/somedomainhere/HelloWorld.class
命令參數(shù)說明:
c:創(chuàng)建新的歸檔文件。v:顯示詳細(xì)輸出(verbose)。m:包含指定的清單文件(manifest.stub)。f:指定輸出文件名(hello.jar)。
執(zhí)行后,將生成 hello.jar,其中包含正確的包結(jié)構(gòu)(com/somedomainhere/HelloWorld.class)和清單文件。
步驟 4:驗(yàn)證 JAR 文件內(nèi)容
您可以使用以下命令查看 JAR 文件的內(nèi)容:
jar tf hello.jar
輸出示例:
META-INF/
META-INF/MANIFEST.MF
com/
com/somedomainhere/
com/somedomainhere/HelloWorld.class
運(yùn)行 JAR 文件
創(chuàng)建 JAR 文件后,可以通過以下命令運(yùn)行:
java -jar hello.jar
java -jar 命令會(huì)讀取清單文件中的 Main-Class 屬性,并執(zhí)行指定的主類。運(yùn)行上述命令將輸出:
Hello, World of Java
在支持的 GUI 平臺(tái)(如 Windows、macOS 或某些 Linux 桌面環(huán)境)上,您可以雙擊 JAR 文件運(yùn)行,前提是系統(tǒng)已將 .jar 文件關(guān)聯(lián)到 Java 運(yùn)行時(shí)環(huán)境(JRE)。
注意:
- 確保已安裝 Java 運(yùn)行時(shí)環(huán)境(JRE)或 JDK。
- 如果 JAR 文件缺少
Main-Class屬性或主類不存在,將拋出異常。
使用 Maven 創(chuàng)建 JAR 文件
對(duì)于大型項(xiàng)目,手動(dòng)創(chuàng)建 JAR 文件可能效率低下。Maven 是一種流行的構(gòu)建工具,可以自動(dòng)化編譯、打包和依賴管理。以下是如何使用 Maven 創(chuàng)建可執(zhí)行 JAR 文件的步驟。
步驟 1:設(shè)置 Maven 項(xiàng)目
創(chuàng)建一個(gè)標(biāo)準(zhǔn)的 Maven 項(xiàng)目,目錄結(jié)構(gòu)如下:
hello-world/
├── pom.xml
└── src
└── main
└── java
└── com
└── somedomainhere
└── HelloWorld.javaHelloWorld.java 的內(nèi)容與之前相同。
步驟 2:配置 pom.xml
在 pom.xml 中,指定項(xiàng)目的基本信息和插件配置。以下是一個(gè)基本的配置,用于生成可執(zhí)行 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>:指定項(xiàng)目打包為 JAR 文件。maven-compiler-plugin:設(shè)置 Java 編譯版本(這里使用 Java 8)。maven-jar-plugin:配置清單文件,指定主類。
運(yùn)行以下命令生成 JAR 文件:
mvn clean package
這將在 target 目錄下生成 hello-world-1.0-SNAPSHOT.jar。您可以運(yùn)行:
java -jar target/hello-world-1.0-SNAPSHOT.jar
步驟 3:包含依賴項(xiàng)(創(chuàng)建胖 JAR)
如果您的項(xiàng)目有外部依賴(如第三方庫(kù)),上述 JAR 文件不包含這些依賴,運(yùn)行時(shí)可能拋出 ClassNotFoundException。要?jiǎng)?chuàng)建包含所有依賴的“胖 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>運(yùn)行以下命令:
mvn clean package
這將生成兩個(gè) JAR 文件:
target/hello-world-1.0-SNAPSHOT.jar:不包含依賴的普通 JAR。target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar:包含所有依賴的胖 JAR。
運(yùn)行胖 JAR:
java -jar target/hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar
優(yōu)點(diǎn):
- 胖 JAR 是自包含的,可以在任何安裝了 Java 的環(huán)境中運(yùn)行,無需額外配置類路徑。
- 便于分發(fā),適合獨(dú)立應(yīng)用程序。
注意:
- 胖 JAR 可能顯著增加文件大小,因?yàn)樗幸蕾嚒?/li>
- 確保依賴的許可證允許這種打包方式。
示例:添加依賴
假設(shè)您的程序使用 Apache Commons Lang 庫(kù)。更新 pom.xml 添加依賴:
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>修改 HelloWorld.java 使用該庫(kù):
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));
}
}重新運(yùn)行 mvn clean package,生成的胖 JAR 將包含 Commons Lang 庫(kù),運(yùn)行時(shí)將輸出:
Hello, world of java
高級(jí)主題
使用 Maven Shade 插件
雖然 maven-assembly-plugin 適用于大多數(shù)場(chǎng)景,但 maven-shade-plugin 提供了更高級(jí)的功能,如包重命名(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>運(yùn)行 mvn clean package 將生成包含所有依賴的 JAR 文件。Shade 插件特別適合需要處理復(fù)雜依賴沖突的項(xiàng)目。
使用 jpackage 工具
自 Java 14 起,JDK 引入了 jpackage 工具,可創(chuàng)建平臺(tái)特定的安裝程序(如 Windows 的 .exe 或 macOS 的 .dmg)。它將應(yīng)用程序和 JRE 打包在一起,適合分發(fā)給非技術(shù)用戶。
示例命令:
jpackage --input target --name HelloWorld --main-jar hello-world-1.0-SNAPSHOT.jar --main-class com.somedomainhere.HelloWorld
由于 jpackage 超出了 JAR 文件的范圍,建議有興趣的讀者參考 Oracle 文檔。
常見問題與注意事項(xiàng)
| 問題 | 解決方案 |
|---|---|
| java -jar 拋出 no main manifest attribute | 確保清單文件中包含 Main-Class 屬性,或在 jar 命令中使用 -e 選項(xiàng)指定主類。 |
| 運(yùn)行胖 JAR 時(shí)出現(xiàn) ClassNotFoundException | 確認(rèn) maven-assembly-plugin 已正確配置,且所有依賴都包含在 JAR 中。 |
| JAR 文件過大 | 考慮使用普通 JAR 并通過類路徑管理依賴,或檢查是否有不必要的依賴。 |
| 雙擊 JAR 文件無法運(yùn)行 | 確保系統(tǒng)安裝了 JRE,并將 .jar 文件關(guān)聯(lián)到 javaw.exe。 |
總結(jié)
打包和運(yùn)行 JAR 文件是 Java 開發(fā)中的核心技能。通過 jar 工具,您可以手動(dòng)創(chuàng)建簡(jiǎn)單的 JAR 文件,適合小型項(xiàng)目或?qū)W習(xí)目的。而 Maven 提供了強(qiáng)大的自動(dòng)化功能,能夠處理復(fù)雜的依賴管理和構(gòu)建流程,使其成為現(xiàn)代 Java 開發(fā)的首選工具。本文通過詳細(xì)的示例和配置,展示了從基礎(chǔ)到高級(jí)的 JAR 文件管理方法。
無論您是初學(xué)者還是經(jīng)驗(yàn)豐富的開發(fā)者,掌握這些技術(shù)將顯著提高您的開發(fā)效率。建議進(jìn)一步探索 Maven 的其他插件(如 maven-shade-plugin)或 jpackage 工具,以滿足更復(fù)雜的部署需求。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring framework體系結(jié)構(gòu)及模塊jar依賴關(guān)系詳解
在本篇文章里小編給大家整理的是關(guān)于spring framework體系結(jié)構(gòu)及模塊jar依賴關(guān)系,對(duì)此有興趣的朋友們可以學(xué)習(xí)下。2019-09-09
SpringBoot ApplicationEvent之事件發(fā)布與監(jiān)聽機(jī)制詳解
本文將深入探討SpringBoot的事件機(jī)制,介紹其核心概念、實(shí)現(xiàn)方法及最佳實(shí)踐,幫助開發(fā)者構(gòu)建更加靈活、可維護(hù)的應(yīng)用架構(gòu),希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
Java?spring注解@PostConstruct實(shí)戰(zhàn)案例講解
我們?cè)赟pring項(xiàng)目中經(jīng)常會(huì)遇到@PostConstruct注解,可能有的伙伴對(duì)這個(gè)注解很陌生,下面這篇文章主要給大家介紹了關(guān)于Java?spring注解@PostConstruct實(shí)戰(zhàn)案例講解的相關(guān)資料,需要的朋友可以參考下2023-12-12
詳解Spring Security的formLogin登錄認(rèn)證模式
對(duì)于一個(gè)完整的應(yīng)用系統(tǒng),與登錄驗(yàn)證相關(guān)的頁面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁面,也就是本文給大家介紹的formLogin模式登錄認(rèn)證模式,感興趣的朋友跟隨小編一起看看吧2019-11-11
Java程序運(yùn)行時(shí)出現(xiàn)亂碼問題的排查與解決方法
本文主要介紹了Java程序運(yùn)行時(shí)出現(xiàn)亂碼問題的排查與解決方法,包括檢查Java源文件編碼、檢查編譯時(shí)的編碼設(shè)置、檢查運(yùn)行時(shí)的編碼設(shè)置、檢查命令提示符的代碼頁、檢查命令提示符的字體、檢查 Java 程序的輸出代碼以及檢查環(huán)境變量,需要的朋友可以參考下2025-03-03

