在Java中生成可執(zhí)行jar的核心是正確配置manifest.mf文件并指定main類。1. 編寫(xiě)包含public Static void main方法的java類;2. 使用javac編譯代碼生成.class文件;3. 創(chuàng)建manifest.mf文件并在其中聲明main-class屬性,注意確保類名正確且文件末尾有換行符;4. 使用jar cfm命令打包生成jar文件;5. 通過(guò)java -jar運(yùn)行jar。若無(wú)法運(yùn)行,需檢查manifest.mf格式、main-class拼寫(xiě)、是否存在必要依賴及java版本兼容性。對(duì)于依賴第三方庫(kù)的項(xiàng)目,推薦使用maven或gradle生成包含所有依賴的“fat jar”,例如通過(guò)maven的maven-assembly-plugin插件配置并執(zhí)行mvn clean package assembly:single命令。manifest.mf還支持class-path、版本描述、密封等屬性,也可通過(guò)命令行使用-cp參數(shù)指定主類運(yùn)行jar而無(wú)需修改manifest.mf。
Java中生成可執(zhí)行JAR,核心在于打包時(shí)正確配置MANIFEST.MF文件,特別是指定包含main方法的類。這使得jvm知道從哪個(gè)類開(kāi)始執(zhí)行程序。配置好后,使用jar命令即可生成。
解決方案:
-
編寫(xiě)包含main方法的Java類
立即學(xué)習(xí)“Java免費(fèi)學(xué)習(xí)筆記(深入)”;
這是最基礎(chǔ)的一步。確保你的Java代碼中有一個(gè)類包含了public static void main(String[] args)方法。例如:
package com.example; public class MainApp { public static void main(String[] args) { System.out.println("Hello, World!"); } }
-
編譯Java代碼
使用javac命令編譯Java文件。
javac com/example/MainApp.java
這將在com/example目錄下生成MainApp.class文件。
-
創(chuàng)建MANIFEST.MF文件
在項(xiàng)目的根目錄下創(chuàng)建一個(gè)名為MANIFEST.MF的文件(注意大小寫(xiě)敏感)。在這個(gè)文件中,指定Main-Class屬性,指向包含main方法的類。
Manifest-Version: 1.0 Main-Class: com.example.MainApp
注意:Main-Class后面必須跟一個(gè)換行符。這是一個(gè)常見(jiàn)的錯(cuò)誤來(lái)源。
-
打包成JAR文件
使用jar命令打包。
jar cfm myapp.jar MANIFEST.MF com/example/*.class
這條命令的含義是:
- c: 創(chuàng)建一個(gè)新的JAR文件。
- f: 指定JAR文件的名稱為myapp.jar。
- m: 使用指定的MANIFEST.MF文件。
- MANIFEST.MF: 指定使用哪個(gè)MANIFEST文件。
- com/example/*.class: 指定要包含在JAR文件中的類文件。
-
運(yùn)行JAR文件
現(xiàn)在,你可以使用java -jar命令運(yùn)行JAR文件了。
java -jar myapp.jar
如果一切順利,你應(yīng)該能在控制臺(tái)上看到”Hello, World!”。
JAR包生成后無(wú)法運(yùn)行:常見(jiàn)問(wèn)題排查
首先,檢查MANIFEST.MF文件。確保Main-Class屬性指向的類名是完全正確的,包括包名。一個(gè)小小的拼寫(xiě)錯(cuò)誤都可能導(dǎo)致程序無(wú)法啟動(dòng)。其次,確保MANIFEST.MF文件最后有一個(gè)換行符。很多人會(huì)忽略這一點(diǎn),導(dǎo)致文件解析失敗。
再者,確認(rèn)JAR包中包含了所有必要的依賴。如果你的程序依賴于其他的JAR包,你需要將這些依賴也包含在可執(zhí)行JAR中,或者在運(yùn)行JAR包時(shí)通過(guò)-classpath參數(shù)指定。
最后,檢查你的Java版本。如果你的代碼是用高版本的Java編譯的,而你嘗試用低版本的Java運(yùn)行,可能會(huì)出現(xiàn)兼容性問(wèn)題。
如何處理依賴第三方庫(kù)的Java項(xiàng)目打包成可執(zhí)行JAR?
如果你的項(xiàng)目依賴了第三方庫(kù),僅僅將你的.class文件打包成JAR是不夠的。你需要將這些依賴也一起打包進(jìn)去。
一種方法是使用Maven或Gradle等構(gòu)建工具,它們可以自動(dòng)處理依賴關(guān)系,并生成包含所有依賴的“fat JAR”或“uber JAR”。這些工具會(huì)自動(dòng)下載所需的依賴,并將它們打包到最終的JAR文件中。
另一種方法是手動(dòng)將所有依賴的JAR文件解壓,然后將解壓后的類文件添加到你的JAR文件中。但這比較繁瑣,容易出錯(cuò),不推薦使用。
例如,使用Maven,你可以在pom.xml文件中聲明你的依賴:
<dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <mainClass>com.example.MainApp</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
然后運(yùn)行mvn clean package assembly:single命令,Maven會(huì)自動(dòng)生成一個(gè)包含所有依賴的可執(zhí)行JAR文件。
除了使用構(gòu)建工具,還可以使用一些專門的JAR打包工具,例如One-JAR或ShadowJar。這些工具可以更靈活地處理依賴關(guān)系,并生成更小的JAR文件。
除了Main-Class,MANIFEST.MF文件還有哪些其他重要的屬性?
MANIFEST.MF文件不僅僅只有Main-Class屬性。它還包含許多其他有用的屬性,可以用來(lái)配置JAR文件的行為。
-
Class-Path: 指定JAR文件依賴的其他JAR文件的路徑。這可以用來(lái)指定外部依賴,而無(wú)需將它們打包到同一個(gè)JAR文件中。
Class-Path: lib/commons-lang3-3.12.0.jar lib/gson-2.8.9.jar
-
Specification-Title, Specification-Version, Specification-Vendor: 用于指定JAR文件的規(guī)范標(biāo)題、版本和供應(yīng)商。這些屬性可以用來(lái)描述JAR文件的用途和來(lái)源。
Specification-Title: My Application Specification-Version: 1.0 Specification-Vendor: My Company
-
Implementation-Title, Implementation-Version, Implementation-Vendor: 用于指定JAR文件的實(shí)現(xiàn)標(biāo)題、版本和供應(yīng)商。這些屬性可以用來(lái)描述JAR文件的具體實(shí)現(xiàn)。
Implementation-Title: My Application Implementation Implementation-Version: 1.0.1 Implementation-Vendor: My Company
-
Sealed: 用于指定JAR文件是否被密封。如果一個(gè)JAR文件被密封,那么它的所有類都必須來(lái)自同一個(gè)包。
Sealed: true
這些屬性可以用來(lái)增強(qiáng)JAR文件的描述性和安全性。
如何通過(guò)命令行指定main方法來(lái)運(yùn)行JAR包,而不用修改MANIFEST.MF?
即使JAR包的MANIFEST.MF文件沒(méi)有指定Main-Class,你仍然可以通過(guò)命令行指定main方法來(lái)運(yùn)行JAR包。
你可以使用以下命令:
java -cp myapp.jar com.example.MainApp
這條命令的含義是:
- java: 運(yùn)行Java虛擬機(jī)。
- -cp myapp.jar: 將myapp.jar添加到類路徑中。
- com.example.MainApp: 指定要運(yùn)行的類。
這種方式不需要修改MANIFEST.MF文件,但需要你手動(dòng)指定包含main方法的類。它在某些情況下可能很有用,例如當(dāng)你需要運(yùn)行一個(gè)沒(méi)有正確配置MANIFEST.MF文件的第三方JAR包時(shí)。