日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

0.07 秒启动一个 SpringBoot 项目!

發布時間:2025/3/15 javascript 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 0.07 秒启动一个 SpringBoot 项目! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫一段簡單的 Java 程序。

public?class?Hello?{public?static?void?main(String[]?args)?{System.out.println("hello?world");} }

通常我們想運行它要這樣。

[root@flash?~]#?javac?Hello.java [root@flash?~]#?java?Hello hello?world

但運行起來需要 jre。

我們換一種方式來編譯這個程序,首先下載一個 GraalVM 的 native-image 工具,然后。

[root@flash?~]#?native-image?Hello [hello:11725]????classlist:???1,031.19?ms,??0.96?GB [hello:11725]????????(cap):???2,624.14?ms,??0.96?GB [hello:11725]????????setup:???3,960.95?ms,??0.96?GB [hello:11725]?????(clinit):?????288.49?ms,??1.72?GB [hello:11725]???(typeflow):???2,642.38?ms,??1.72?GB [hello:11725]????(objects):???3,803.54?ms,??1.72?GB [hello:11725]???(features):???1,176.79?ms,??1.72?GB [hello:11725]?????analysis:???8,288.82?ms,??1.72?GB [hello:11725]?????universe:?????909.14?ms,??1.75?GB [hello:11725]??????(parse):?????801.67?ms,??1.75?GB [hello:11725]?????(inline):???1,096.07?ms,??2.32?GB [hello:11725]????(compile):???7,352.50?ms,??2.37?GB [hello:11725]??????compile:??10,146.59?ms,??2.37?GB [hello:11725]????????image:???1,639.93?ms,??2.37?GB [hello:11725]????????write:?????682.24?ms,??2.37?GB [hello:11725]??????[total]:??26,855.67?ms,??2.37?GB #?Printing?build?artifacts?to:?.../hello.build_artifacts.txt

執行完這個命令后,發現當前目錄多了個 hello 文件。

直接執行它,可以成功!

[root@flash?~]#?./hello hello?world

而且注意,這個是可以直接以二進制形式運行的,不依賴 jre。

也就是說,一個 Java 程序,被這個 native-image 編譯成了本地代碼!

這項技術來自于 GraalVM 的一個特性,在其官網的文檔中可以了解到,GraalVM 主要有三大特性:

  • 通過新的 JIT 技術使 Java 程序更快運行

  • 多語言支持

  • 構建 JVM 無關的本地鏡像

  • 這個 native-image 技術就是其中的第三點,即將 Java 代碼編譯成 JVM 無關的本地鏡像,使其可以直接以二進制的方式運行起來。

    除了運行方便之外,我們對比一下這倆的文件大小啟動時間

    [root@flash?~]#?ll -rw-r--r--??1?flash??staff???415B?10?27?15:50?Hello.class -rwxr-xr-x??1?flash??staff????10M?10?27?15:51?hello[root@flash?~]#?time?java?Hello hello?world java?Hello??0.09s?user?0.03s?system?113%?cpu?0.106?total[root@flash?~]#?time?./hello hello?world ./hello??0.00s?user?0.01s?system?34%?cpu?0.032?total

    總結個表格。

    Hello.class??415B? 0.12s

    hello? 10M? 0.01s

    可以看出,啟動時間大大縮短了!但文件大小卻大大增加了。

    不過要知道,運行 Hello.class 要整個 jre 的支持,而運行二進制的 hello 卻不需要,這部分文件大小的差距,在小代碼上對比并不公平。

    當然,啟動時間也都是毫秒級的,差距也不足以說明問題。下面我們試著用這種方式,對比一個 Spring Boot 項目。

    有一點要說明的是,GraalVM 的本地編譯對 Java 代碼有很多的限制,有的時候需要配合配置文件才能成功,比如不支持動態類加載、反射、序列化等,具體可以見這里:

    https://www.GraalVM.org/reference-manual/native-image/Limitations/

    可是 Spring 項目中可是大量充斥著這些,我們需要增加好多配置文件,才能成功本地編譯一個 Spring Boot 項目。

    好在,Spring 已經為我們考慮好這些事情了,提供了一個專門為 native 而生的 Spring Boot 依賴項,最方便的是我們新建項目的時候可以直接從 start.spring.io 生成。

    然后可以直接用 mvn 命令來打包一個本地鏡像。

    [root@flash?~]#?mvn?package?-Pnative ... [INFO]?Executing:?...native-image?-cp?...?-H:Name=demo-1 ... [demo-1:7725]????classlist:???1,695.81?ms,??0.94?GB [demo-1:7725]????????(cap):???1,932.48?ms,??0.94?GB [demo-1:7725]????????setup:???3,287.65?ms,??0.94?GB [demo-1:7725]?????(clinit):???2,256.61?ms,??5.68?GB [demo-1:7725]???(typeflow):??18,462.41?ms,??5.68?GB [demo-1:7725]????(objects):??17,848.47?ms,??5.68?GB [demo-1:7725]???(features):???4,646.24?ms,??5.68?GB [demo-1:7725]?????analysis:??45,521.71?ms,??5.68?GB [demo-1:7725]?????universe:???2,624.03?ms,??5.68?GB [demo-1:7725]??????(parse):???1,917.71?ms,??5.68?GB [demo-1:7725]?????(inline):???6,021.71?ms,??5.93?GB [demo-1:7725]????(compile):??30,497.99?ms,??6.06?GB [demo-1:7725]??????compile:??42,184.66?ms,??6.06?GB [demo-1:7725]????????image:???8,700.31?ms,??5.90?GB [demo-1:7725]????????write:???1,647.51?ms,??5.90?GB [demo-1:7725]??????[total]:?106,412.95?ms,??5.90?GB #?Printing?build?artifacts?to:?.../demo-1.build_artifacts.txt

    同樣,我們用傳統的 jar 包方式打包一個 jar 文件,對比一下。

    -rwxr-xr-x??1?flash??staff????66M?Nov??2?16:11?demo-1 -rw-r--r--??1?flash??staff????17M?Nov??2?16:09?demo-1-exec.jar

    這回大小已經沒差那么多了,但仍然是二進制的本地包大。不過這僅僅是幾乎空的 Spring Boot 項目,隨著項目依賴的包越來越多,二進制的文件大小會越來越有優勢,這是后話了。

    我們再來對比一下啟動速度,首先是傳統的 jar 包運行。

    [root@flash?~]#?java?-jar?demo-1-exec.jar?.???____??????????_????????????__?_?_/\\?/?___'_?__?_?_(_)_?__??__?_?\?\?\?\ (?(?)\___?|?'_?|?'_|?|?'_?\/?_`?|?\?\?\?\\\/??___)|?|_)|?|?|?|?|?||?(_|?|??)?)?)?)'??|____|?.__|_|?|_|_|?|_\__,?|?/?/?/?/=========|_|==============|___/=/_/_/_/::?Spring?Boot?::????????????????(v2.5.6)2021-11-02?16:36:11.192??INFO?9468?---?[main]?com.example.demo1.Demo1Application???????:?Starting?Demo1Application?v0.0.1-SNAPSHOT?using?Java?11.0.12?on?sunyiming07deMacBook-Pro.local?with?PID?9468?(/Users/sunyiming07/IdeaProjects/graalvm-demos/springboot/demo/demo-1/target/demo-1-0.0.1-SNAPSHOT-exec.jar?started?by?sunyiming07?in?/Users/sunyiming07/IdeaProjects/graalvm-demos/springboot/demo/demo-1/target) 2021-11-02?16:36:11.195??INFO?9468?---?[main]?com.example.demo1.Demo1Application???????:?No?active?profile?set,?falling?back?to?default?profiles:?default 2021-11-02?16:36:12.097??INFO?9468?---?[main]?o.s.b.w.embedded.tomcat.TomcatWebServer??:?Tomcat?initialized?with?port(s):?8080?(http) 2021-11-02?16:36:12.110??INFO?9468?---?[main]?o.apache.catalina.core.StandardService???:?Starting?service?[Tomcat] 2021-11-02?16:36:12.110??INFO?9468?---?[main]?org.apache.catalina.core.StandardEngine??:?Starting?Servlet?engine:?[Apache?Tomcat/9.0.54] 2021-11-02?16:36:12.164??INFO?9468?---?[main]?o.a.c.c.C.[Tomcat].[localhost].[/]???????:?Initializing?Spring?embedded?WebApplicationContext 2021-11-02?16:36:12.164??INFO?9468?---?[main]?w.s.c.ServletWebServerApplicationContext?:?Root?WebApplicationContext:?initialization?completed?in?917?ms 2021-11-02?16:36:12.484??INFO?9468?---?[main]?o.s.b.w.embedded.tomcat.TomcatWebServer??:?Tomcat?started?on?port(s):?8080?(http)?with?context?path?'' 2021-11-02?16:36:12.494??INFO?9468?---?[main]?com.example.demo1.Demo1Application???????:?Started?Demo1Application?in?2.033?seconds?(JVM?running?for?2.504)

    2.033 秒,已經慢下來了,不過正常的空 Spring Boot 項目也就這樣。

    再看看本地鏡像啟動速度。

    [root@flash?~]#?./demo-1 2021-11-02?16:38:33.141??INFO?9724?---?[main]?o.s.nativex.NativeListener???????????????:?This?application?is?bootstrapped?with?code?generated?with?Spring?AOT.???____??????????_????????????__?_?_/\\?/?___'_?__?_?_(_)_?__??__?_?\?\?\?\ (?(?)\___?|?'_?|?'_|?|?'_?\/?_`?|?\?\?\?\\\/??___)|?|_)|?|?|?|?|?||?(_|?|??)?)?)?)'??|____|?.__|_|?|_|_|?|_\__,?|?/?/?/?/=========|_|==============|___/=/_/_/_/::?Spring?Boot?::????????????????(v2.5.6)2021-11-02?16:38:33.143??INFO?9724?---?[main]?com.example.demo1.Demo1Application???????:?Starting?Demo1Application?v0.0.1-SNAPSHOT?using?Java?11.0.12?on?sunyiming07deMacBook-Pro.local?with?PID?9724?(/Users/sunyiming07/IdeaProjects/graalvm-demos/springboot/demo/demo-1/target/demo-1?started?by?sunyiming07?in?/Users/sunyiming07/IdeaProjects/graalvm-demos/springboot/demo/demo-1/target) 2021-11-02?16:38:33.143??INFO?9724?---?[main]?com.example.demo1.Demo1Application???????:?No?active?profile?set,?falling?back?to?default?profiles:?default 2021-11-02?16:38:33.178??INFO?9724?---?[main]?o.s.b.w.embedded.tomcat.TomcatWebServer??:?Tomcat?initialized?with?port(s):?8080?(http) 2021-11-02?16:38:33.178??INFO?9724?---?[main]?o.apache.catalina.core.StandardService???:?Starting?service?[Tomcat] 2021-11-02?16:38:33.178??INFO?9724?---?[main]?org.apache.catalina.core.StandardEngine??:?Starting?Servlet?engine:?[Apache?Tomcat/9.0.54] 2021-11-02?16:38:33.184??INFO?9724?---?[main]?o.a.c.c.C.[Tomcat].[localhost].[/]???????:?Initializing?Spring?embedded?WebApplicationContext 2021-11-02?16:38:33.184??INFO?9724?---?[main]?w.s.c.ServletWebServerApplicationContext?:?Root?WebApplicationContext:?initialization?completed?in?41?ms 2021-11-02?16:38:33.204??INFO?9724?---?[main]?o.s.b.w.embedded.tomcat.TomcatWebServer??:?Tomcat?started?on?port(s):?8080?(http)?with?context?path?'' 2021-11-02?16:38:33.204??INFO?9724?---?[main]?com.example.demo1.Demo1Application???????:?Started?Demo1Application?in?0.078?seconds?(JVM?running?for?0.08)我去!0.078 秒!!!

    我還真從來沒有啟動 Spring Boot 項目體驗過這么極速的狀態呢!!!容我高興一會兒。

    看吧,前面的 hello world 項目看不出什么,現在的 Spring Boot 項目,優勢就已經完全出來了,啟動速度秒殺呀!

    可想而知,我們原來啟動可能要幾分鐘才成功的 Spring Boot 項目,會被這個 GraalVM 優化到多少呢?想想就激動!

    不過這個我還沒有試,光是跑這個 Spring Boot 空項目就忙活了好久,一直報各種各樣奇怪的錯誤,等我再熟練熟練的。

    剛剛也說了,想通過 GraalVM 的 native-image 功能編譯一個 Java 程序,有很多限制,比如不支持動態類加載、反射、動態代理、JNI、序列化以及 invoke dynamic 指令等。

    這是由于,AOT 這種提前編譯的技術,需要一個封閉空間假設,即在編譯期就能夠把運行期所有需要的東西都準備好,但 Java 的好多特性就是和這種封閉空間假設相沖突的。

    Java 啟動后隨著程序不斷運行,JVM 將一部分代碼編譯成本地代碼,這個叫 JIT 技術,它是在程序運行起來之后不斷分析而做的編譯,所以它不受封閉空間假設的限制。

    說回 GraalVM 的 AOT,比如程序中有個反射,這就屬于運行時才會知道有這樣一個 Student 類被需要的情況。

    Class.forName("com.flash.Student")

    當然,GraalVM 會通過掃描這些反射方法的調用,來嘗試分析用到了哪些類。

    如果分析不出來,就需要程序員手動配置,告訴 GraalVM 有哪些類要反射。

    [{name:?"com.flash.Student",allDeclaredConstructors:?true,allPublicMethods:?true},{name:?"com.flash.Teacher",fileds:?[{name:?"teach"},?{name:?"talk"}],methods:?[{name:?"<init>",parameterTypes:?["char[]"]}]},//?…… ]

    但這樣肯定是反人性的。

    自己寫的代碼和依賴還好,但如果是使用第三方組建,比如人人都用的 Spring,肯定不能由程序員來去寫這些配置文件。

    那就只有讓 Spring 官方提供這些配置,讓程序員仍然是簡單寫一些 maven 依賴就能把項目跑起來,才能把這個技術推廣出去,這也是剛剛 Spring Native 項目存在的意義。

    今天簡單給大家分享下 GraalVM 的使用,這個技術基本還沒有公司大規模在用,還達不到工業級的成熟,不過未來云原生領域要求小包快速啟動兩個特性,GraalVM 的未來說不定有大舞臺呢。

    總結

    以上是生活随笔為你收集整理的0.07 秒启动一个 SpringBoot 项目!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。