抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

1️⃣jar包

怎么来

以 IDEA maven项目为例,jar包由Java工程通过mvn pakage命令打包生成的。(题外话:web项目打包成war包)。

怎么运行

1
java -jar xx.jar

有什么

以spring boot项目为例,包内结构如下:

1
2
3
4
5
6
7
8
+- BOOT-INF	# 应用文件夹
+- classes # 编译后的classes文件
+- lib # 第三方依赖
+- META-INF # 打包信息
+- maven # maven信息,pom文件
+- MANIFEST.MF(文件)
+- org # spring boot 相关class文件
+- springframework

配置文件:MANIFEST.MF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
# 定义自己项目的启动类
Start-Class: com.example.demo.DemoApplication
# 定义项目文件路径
Spring-Boot-Classes: BOOT-INF/classes/
# 定义项目依赖路径
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.5.15
Created-By: Maven JAR Plugin 3.2.2
# 程序入口启动类
Main-Class: org.springframework.boot.loader.JarLauncher

spring boot项目jar包启动流程:

JarLauncher按照MANIFEST.MFSpring-Boot-ClassesSpring-Boot-Lib的配置,将类文件和依赖加载到classpath下,然后调用Start-Class配置的应用启动类。

2️⃣jar生成原理

  • 准备一份java文件,例如Test.java:

    1
    2
    3
    4
    5
    public class Test {
    public static void main(String[] args) {
    System.out.println("hello jar");
    }
    }
  • javac Test.java生成Test.class文件

  • jar -cvf test.jar Test.class

    c 表示要创建一个新的jar包

    v 表示创建的过程中在控制台输出创建过程的一些信息,

    f 表示给生成的jar包命名

  • 运行 test.jar时报错,test.jar中没有主清单属性

    原因是:test.jar中META-INF文件夹下的MENIFEST.MF文件缺少了Main-Class属性

修复:

1
2
3
4
5
6
7
8
9
# 列出文件清单
jar -tf test.jar
# 将MENIFEST.MF文件解压出来
jar -xf test.jar META-INF/MANIFEST.MF
# 将下面代码追加到MENIFEST.MF文件中
Main-Class: Test
# 将修改后的MENIFEST.MF文件写入到jar中
jar -ufm test.jar META-INF/MANIFEST.MF
# (m表示更新文件中的清单文件,不更新可以不用)
  • 此时java -jar test.jar就可以运行了。

maven下修复:

  1. pom.xml文件中配置maven-jar-plugin插件,指定archivemanifestmainClass属性。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
    <archive>
    <manifest>
    <addClasspath>true</addClasspath>
    <mainClass>你的主类全名</mainClass>
    </manifest>
    </archive>
    </configuration>
    </plugin>
    </plugins>
    </build>

​ 将你的主类全名替换为你的应用程序的主类的完整名称,例如com.example.MainApp

  1. 如果你的项目是一个包含多个模块的Maven项目,确保每个模块的pom.xml中都有正确的主类配置。
  2. 如果你的应用程序是一个可执行的WAR,确保你的pom.xml中配置了正确的<packaging>类型,并且maven-war-plugin配置中包含了正确的web.xml

3️⃣更新后重新打包

  • 解压

    jar -xvf xx.jar

  • 修改改后,重新打包

    jar -cvfM0 xx.jar BOOT-INF/ META-INF/ org/

评论