在 Java 中,使用“java -jar”命令能够启动项目主要基于以下原理:
一、JAR 文件结构
JAR(Java Archive)文件是一种包含 Java 类文件、资源文件和元数据的归档文件格式。它本质上是一个压缩文件,通常以“.jar”为扩展名。一个典型的 Java 项目经过编译打包后会生成一个 JAR 文件,其中包含了项目的所有编译后的类文件、配置文件、静态资源等。
可执行的 jar (以 SpringBoot 的 FAT JAR 为例)
这个 jar 是从 start.spring.io 上下载下来的一个最简单的 demo 打包来的
├── BOOT-INF
│ ├── classes
│ │ ├── application.properties
│ │ └── com
│ │ └── example # 应用的.class 文件目录
│ │ └── demo
│ │ └── DemoApplication.class
│ └── lib # 这里存放的是应用的 Maven 依赖的jar包文件
│ ├── javax.annotation-api-1.3.2.jar
│ ├── jul-to-slf4j-1.7.26.jar
│ ├── log4j-api-2.11.2.jar
│ ├── log4j-to-slf4j-2.11.2.jar
│ ├── logback-classic-1.2.3.jar
│ ├── logback-core-1.2.3.jar
│ ├── slf4j-api-1.7.26.jar
│ ├── snakeyaml-1.23.jar
│ ├── spring-aop-5.1.8.RELEASE.jar
│ ├── spring-beans-5.1.8.RELEASE.jar
│ ├── spring-boot-2.1.6.RELEASE.jar
│ ├── spring-boot-autoconfigure-2.1.6.RELEASE.jar
│ ├── spring-boot-starter-2.1.6.RELEASE.jar
│ ├── spring-boot-starter-logging-2.1.6.RELEASE.jar
│ ├── spring-context-5.1.8.RELEASE.jar
│ ├── spring-core-5.1.8.RELEASE.jar
│ ├── spring-expression-5.1.8.RELEASE.jar
│ └── spring-jcl-5.1.8.RELEASE.jar
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── com.example
│ └── demo
│ ├── pom.properties
│ └── pom.xml
└── org
└── springframework
└── boot
└── loader #存放的是 Spring boot loader 的 class 文件
├── ExecutableArchiveLauncher.class
├── JarLauncher.class
├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
├── LaunchedURLClassLoader.class
├── Launcher.class
├── MainMethodRunner.class
├── PropertiesLauncher$1.class
├── PropertiesLauncher$ArchiveEntryFilter.class
├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
├── PropertiesLauncher.class
├── WarLauncher.class
├── archive
│ ├── Archive$Entry.class
│ ├── ...
├── data
│ ├── RandomAccessData.class
│ ├── ...
├── jar
│ ├── AsciiBytes.class
│ ├── ...
└── util
└── SystemPropertyUtils.class
二、Java 虚拟机(JVM)的作用
- 当执行“java -jar”命令时,首先会启动 Java 虚拟机。JVM 是一个虚拟的计算机,它负责加载、验证、解释和执行 Java 字节码。
- JVM 会根据命令中的参数找到要执行的 JAR 文件,并将其加载到内存中。这个过程包括读取 JAR 文件的元数据,如清单文件(MANIFEST.MF)等,以确定项目的入口点。
三、清单文件指定入口点
- 在一个可执行的 JAR 文件中,通常会包含一个清单文件(MANIFEST.MF),这个文件位于 JAR 文件的 META-INF 目录下。
- 清单文件可以指定项目的主类,即项目的入口点。例如,在清单文件中可以添加以下内容:
这里指定了主类为“com.example.MainApp”。当 JVM 加载 JAR 文件时,会根据这个指定的主类来找到项目的入口点并开始执行。Main-Class: com.example.MainApp
四、类加载机制
- JVM 采用类加载器机制来加载项目中的类。当项目启动时,JVM 会使用引导类加载器、扩展类加载器和应用类加载器等按照特定的顺序去查找和加载项目所需的类。
- 一旦找到主类,JVM 会加载这个主类,并开始执行其中的静态初始化块和静态方法(通常是 main 方法)。这个 main 方法是项目的入口点,它负责启动整个项目的执行流程,包括创建对象、调用其他方法、处理用户输入等。
“java -jar”命令能够启动项目是因为它利用了 Java 虚拟机的强大功能,通过加载 JAR
文件、查找主类并执行主类的入口方法来启动整个 Java 项目。这种方式使得 Java
项目可以方便地打包和分发,并且可以在不同的平台上通过相同的命令来启动运行。