欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot應(yīng)用能直接運行java -jar的原因分析

 更新時間:2024年03月06日 09:45:36   作者:hbqst  
這篇文章主要介紹了SpringBoot應(yīng)用為什么能直接運行java -jar,首先明確一點,普通jar包是不能直接運行的,比如工具類jar,要能運行,至少得要一個main函數(shù)作為入口吧?本文給大家介紹了詳細(xì)的原因分析,需要的朋友可以參考下

首先明確一點,普通jar包是不能直接運行的,比如工具類jar

要能運行,至少得要一個main函數(shù)作為入口吧?

SpringBoot應(yīng)用確實有個main函數(shù),那么問題來了,java -jar是怎么找到這個main函數(shù)運行的?

先說答案

是因為引入了spring-boot-maven-plugin插件

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

不信?

現(xiàn)在不使用這個插件,將SpringBoot應(yīng)用打個jar包

target目錄產(chǎn)出文件如下

在這里插入圖片描述

注意此時的jar體積為3202KB,內(nèi)容只包含了項目中的代碼和resources下的文件

在這里插入圖片描述

嘗試java -jar運行,報錯沒有主清單屬性

在這里插入圖片描述

這是把spring-boot-maven-plugin插件加上,再次打包

target目錄如下

在這里插入圖片描述

jar包體積變大了!另外多出一個jar.origin,大小和之前jar包的一樣

當(dāng)然我們只需要關(guān)系jar即可

查看jar包中的內(nèi)容,不僅包含了自己寫的類(classes),還將依賴的第三方j(luò)ar包全部裝了進(jìn)來(lib),這種jar被稱為fat jar

在這里插入圖片描述

這時使用java -jar命令,成功運行!

在這里插入圖片描述

按照常規(guī)思路,一定是要找到main方法所在的這個類,然后去運行里面的main方法

其實,當(dāng)執(zhí)行java -jar時,會自動去找一個叫MANIFEST.MF的文件,然后根據(jù)其中的Main-Class找到入口類,并執(zhí)行其中的main方法

在這里插入圖片描述

而SpringBoot的jar包的這個文件,就是spring-boot-maven-plugin這個插件生成的

這個文件中的內(nèi)容如下

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Archiver-Version: Plexus Archiver
Built-By: yimin
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.example.k8sdemo.K8sDemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.6.13
Created-By: Apache Maven 3.8.8
Build-Jdk: 1.8.0_392
Main-Class: org.springframework.boot.loader.JarLauncher

好家伙,Main-Class居然不是我們自己寫的那個類

而是org.springframework.boot.loader.JarLauncher

想要查看這個類,先引入以下依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-loader</artifactId>
</dependency>

JarLauncher的main函數(shù)以及方法調(diào)用如下

public static void main(String[] args) throws Exception {
	new JarLauncher().launch(args);
}

protected void launch(String[] args) throws Exception {
	if (!isExploded()) {
		JarFile.registerUrlProtocolHandler();
	}
	ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
	String jarMode = System.getProperty("jarmode");
	String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
	launch(args, launchClass, classLoader);
}


@Override
protected String getMainClass() throws Exception {
	String mainClass = getProperty(MAIN, "Start-Class");
	if (mainClass == null) {
		throw new IllegalStateException("No '" + MAIN + "' or 'Start-Class' specified");
	}
	return mainClass;
}


protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
	Thread.currentThread().setContextClassLoader(classLoader);
	createMainMethodRunner(launchClass, args, classLoader).run();
}


protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
	return new MainMethodRunner(mainClass, args);
}

public void run() throws Exception {
	Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
	Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
	mainMethod.setAccessible(true);
	mainMethod.invoke(null, new Object[] { this.args });
}

總結(jié)一下就是

  • 創(chuàng)建一個自定義的類加載器LaunchedURLClassLoader
  • 使用這個自定義的ClassLoader去加載我們自己寫的main方法類,這個類由MANIFEST.MF中Start-Class定義
  • 反射獲取main方法,然后執(zhí)行

以上就是SpringBoot應(yīng)用能直接運行java -jar的原因分析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot直接運行java -jar的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論