首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JAR 包指定 Main 類啟動完全指南:-cp vs -jar 區別與最佳實踐

     編輯:Java 相關知識

兩種啟動方式的本質區別

特性java -jar app.jarjava -cp app.jar com.example.Main
入口點MANIFEST.MF 中 Main-Class 屬性命令行顯式指定全限定類名
Classpath忽略外部 -cp/-classpath,僅用 JAR 內 Class-Path完全由 -cp 控制,可混合多個 JAR/目錄
多 Main 類支援單一固定入口可任意指定任意含 main 方法的類
適用場景標準發布、生產部署測試、多入口工具、調試特定類

場景一:MANIFEST.MF 指定主類(標準打包)

Maven 配置

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.example.Application</mainClass>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
            </manifest>
        </archive>
    </configuration>
</plugin>

Spring Boot Fat JAR(推薦生產)

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <mainClass>com.example.Application</mainClass>
        <layout>ZIP</layout> <!-- 或 JAR -->
    </configuration>
    <executions>
        <execution>
            <goals><goal>repackage</goal></goals>
        </execution>
    </executions>
</plugin>

啟動:java -jar myapp.jar 或 java -jar myapp.jar --spring.profiles.active=prod

場景二:命令行指定主類(多入口/測試)

# 基本語法
java -cp target/myapp.jar com.example.tools.DataMigration arg1 arg2

# 包含依賴(需手動展開或使用 classpath 通配符 Java 6+)
java -cp "target/myapp.jar:target/lib/*" com.example.tools.BatchJob

# Windows 路徑分隔符為分號
java -cp "target/myapp.jar;target/lib/*" com.example.tools.BatchJob

場景三:OneJar / Shade Plugin 打包後的特殊處理

OneJar 將依賴包嵌套在 JAR 內部,類加載器特殊,無法直接用 -cp 指定主類。必須使用 java -jar 或解壓後重新組織 classpath。

進階技巧:動態發現並選擇 Main 類

#!/bin/bash
# list-mains.sh:掃描 JAR 內所有含 main 方法的類
JAR_FILE=$1
unzip -q -c "$JAR_FILE" META-INF/MANIFEST.MF 2>/dev/null | grep -i main-class || true

# 使用 javap 反編譯查找(較慢但準確)
unzip -l "$JAR_FILE" | grep '\.class$' | awk '{print $4}' | sed 's/\.class$//; s/\//./g' | \
while read class; do
    if unzip -p "$JAR_FILE" "${class//./\/}.class" | javap -c - | grep -q "main.*String\[\]"; then
        echo "$class"
    fi
done

最佳實踐總結

  1. 生產環境:統一使用 maven-jar-plugin 或 spring-boot-maven-plugin 固化 Main-Class,啟動腳本只需 java -jar app.jar $ARGS。
  2. 開發/測試多入口:在 IDE Run Configuration 或啟動腳本中使用 -cp 顯式指定主類,避免修改 MANIFEST。
  3. 參數傳遞:java -jar app.jar --server.port=8081(Spring Boot)或 java -cp app.jar com.Main arg1 arg2(原生 args 數組)。
  4. 模塊化(JPMS):Java 9+ 模塊化項目需用 --module/-m 啟動,而非 -jar/-cp。

常見錯誤排查

  • no main manifest attribute:JAR 未設置 Main-Class,用 -cp 指定或重新打包。
  • ClassNotFoundException:-cp 路徑缺少依賴 JAR,檢查 Class-Path 或展開 fat-jar。
  • Error: Could not find or load main class:類名拼寫錯誤、包名不匹配、或模塊化項目用法錯誤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved