SpringBoot應(yīng)用能直接運(yùn)行java -jar的原因分析
首先明確一點(diǎn),普通jar包是不能直接運(yùn)行的,比如工具類jar
要能運(yùn)行,至少得要一個(gè)main函數(shù)作為入口吧?
SpringBoot應(yīng)用確實(shí)有個(gè)main函數(shù),那么問題來了,java -jar是怎么找到這個(gè)main函數(shù)運(yùn)行的?
先說答案
是因?yàn)橐肓藄pring-boot-maven-plugin插件
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
不信?
現(xiàn)在不使用這個(gè)插件,將SpringBoot應(yīng)用打個(gè)jar包
target目錄產(chǎn)出文件如下

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

嘗試java -jar運(yùn)行,報(bào)錯(cuò)沒有主清單屬性

這是把spring-boot-maven-plugin插件加上,再次打包
target目錄如下

jar包體積變大了!另外多出一個(gè)jar.origin,大小和之前jar包的一樣
當(dāng)然我們只需要關(guān)系jar即可
查看jar包中的內(nèi)容,不僅包含了自己寫的類(classes),還將依賴的第三方j(luò)ar包全部裝了進(jìn)來(lib),這種jar被稱為fat jar

這時(shí)使用java -jar命令,成功運(yùn)行!

按照常規(guī)思路,一定是要找到main方法所在的這個(gè)類,然后去運(yùn)行里面的main方法
其實(shí),當(dāng)執(zhí)行java -jar時(shí),會(huì)自動(dòng)去找一個(gè)叫MANIFEST.MF的文件,然后根據(jù)其中的Main-Class找到入口類,并執(zhí)行其中的main方法

而SpringBoot的jar包的這個(gè)文件,就是spring-boot-maven-plugin這個(gè)插件生成的
這個(gè)文件中的內(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居然不是我們自己寫的那個(gè)類
而是org.springframework.boot.loader.JarLauncher
想要查看這個(gè)類,先引入以下依賴
<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)建一個(gè)自定義的類加載器
LaunchedURLClassLoader - 使用這個(gè)自定義的ClassLoader去加載我們自己寫的main方法類,這個(gè)類由MANIFEST.MF中Start-Class定義
- 反射獲取main方法,然后執(zhí)行
以上就是SpringBoot應(yīng)用能直接運(yùn)行java -jar的原因分析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot直接運(yùn)行java -jar的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java如何使用Iterator迭代器刪除集合重復(fù)選項(xiàng)
這篇文章主要介紹了Java如何使用Iterator迭代器刪除集合重復(fù)選項(xiàng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Java Long轉(zhuǎn)JSON出現(xiàn)精度丟失問題及解決
Java Long類型轉(zhuǎn)JSON時(shí)可能因JSON的通用數(shù)字類型不指定位數(shù)大小及JavaScript整數(shù)表達(dá)精度限制導(dǎo)致精度丟失,解決方法包括在Java對象中為Long類型字段添加@JsonFormat(shape=JsonFormat.Shape.STRING)注解,或在Spring框架中配置ObjectMapper以全局序列化行為2025-12-12
Jmeter多臺(tái)機(jī)器并發(fā)請求實(shí)現(xiàn)壓力性能測試
這篇文章主要介紹了Jmeter多臺(tái)機(jī)器并發(fā)請求實(shí)現(xiàn)壓力性能測試,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
spring異步service中處理線程數(shù)限制詳解
這篇文章主要給大家介紹了關(guān)于spring異步service中處理線程數(shù)限制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
SpringBoot DFA實(shí)現(xiàn)敏感詞過濾功能
傳統(tǒng)的字符串查找方式在處理大量敏感詞時(shí)性能急劇下降,而正則表達(dá)式在匹配復(fù)雜規(guī)則時(shí)更是捉襟見肘,今天,介紹一種基于 DFA(有限狀態(tài)自動(dòng)機(jī))算法的高效敏感詞過濾方案,感興趣的可以了解下2025-11-11

