您好,登錄后才能下訂單哦!
這是一個全新的工具,由我們設計的全新工具,所以我們可以來規劃它未來長什么樣子。
我們在上一篇:fast-loader(一)起源里討論過,它最最最基本需要達到的目標應該是對類的按需裝載,從而節約資源提升性能和資源利用率。
為了達到這個目標,我們就不能讓JVM自行裝載業務程序包,而是JVM裝載fast-loader,由fast-loader對業務程序包進行裝載,如上一篇的圖
因此,對于JVM而言,它并不清楚業務程序包的存在,而fast-loader需要關心的就是業務程序包,相當于fast-loader接管了JVM對業務程序運行的能力。
屆時,對業務程序的運行將變成如下
java -jar fast-loader.jar run some-biz-program
所以,fast-loader應該具備啟動一個應用程序main方法的能力,同時,它還是一個應用程序。
fast-loader為了啟動應用程序,如果目標是jar包的話,需要能將jar裝入內存,但如果整體裝入的話,將會導致內存占用,這樣fast-loader就無法節約內存,因此需要避免jar直接裝入內存的情況。
考慮到jar包本質上是zip格式,同時參考tomcat對war包的處理邏輯,fast-loader首次啟動時可以將jar進行解壓到文件夾,再按需進行讀取文件,這樣雖然首次啟動慢了些,但之后運行效率將大大提升。
因此,fast-loader的需要能對jar進行解壓縮到文件的能力。
一個程序不僅僅是一個jar包,它可能是一堆jar的組成,所以,fast-loader還需要能將這堆jar解壓后管理起來的能力。
程序運行過程中會訪問各類資源,特別是springboot打包結構里,jar包內又包含jar包,考慮到springboot的風行程度,fast-loader需要具備對springboot包格式的兼容能力。
整理到一起
前面定義了fast-loader的能力,我們再進行一個簡單梳理,看看它的調用應該是怎么進行的
所以,從用例的角度來看的話,它應該是這樣的
再對它的能力進行對齊和歸類,如下
各自職責如下
FastLoaderMain
:Main方法所在類,負責啟動業務APP并調用其main方法; FastClassLoader
:負責轉載業務類定義到內存中; JarUtil
:負責解壓縮業務jar包,如果存在多個jar包的話,還需要解壓到對應的文件夾中; FileUtil
:負責對解壓縮出來的.class以及資源文件進行管理; 轉換成類圖
當然,除了這些類之外,肯定還有其它類存在,但這幾個類為核心。
jar解壓縮至指定的文件夾,考慮到配置的簡便以及第三方庫的數量較多,可以設計為
對存在多個相同版本的包的情況下,考慮到jar文件名稱不同(自帶版本號),將會釋放到不同文件夾當中。
但是,在查找類文件的時候,由于包沖突原因可能導致查找時候無法明確指定那個版本,因此這里設定規則:
但出現同類庫多個版本時,直接使用最新版本
為了適配這個規則,我們需要對以上解壓縮的文件夾進行調整,包括
變更后的文件夾格式如下
fast-loader首次加載時涉及解壓,會導致啟動速度比之前下降,而首次之后因為按需加載,總體性能可以比原先得到提升,但是每次都去讀取磁盤也是一種比較慢的方式,可以考慮設計優化。
實際app執行中,多數情況下,無論多少次的啟動,其使用的類都基本相同。
基于這個理念,我們可以考慮將app第一次啟動到關閉過程中使用到的類復制到另外一個文件夾中,之后app啟動時默認裝載此路徑下所有類,這樣就可以類似緩存的作用,一定程度上加快啟動速度。
所以,文件夾部分還可以做這樣的優化
其中used文件夾為所有類定義后需要寫入的文件夾,也是所有使用過的類的緩存文件夾。
這里有個小點需要注意,寫入緩存成功與否不影響類定義,所以應該采用異步寫入以避免堵塞。
springboot有它獨有的包體結構,其定義在MATE-INF/MANIFEST.MF文件中,舉個案例
Manifest-Version: 1.0
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Start-Class: me.van.DemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.6.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.JarLauncher
通過這個文件,我們需要去適配的包括
Spring-Boot-Classes
:需要將所有類解壓縮至應用包文件夾目錄下; Spring-Boot-Lib
:依賴的第三方庫,需要將其解壓縮成jar包后再二次解壓; 不同jar包可能存在同名的資源文件,而ClassLoader
對資源文件的獲取是允許多個同時獲取到的,而我們調整了對資源位置的定義,那么我們也要去重寫“如何讀取資源文件”這類方法。
同名文件可能存在兩類
- 相同hash值,意味著文件內容相同,直接取其一即可;
- 不同hash值,需要判斷其MANIFEST.MF文件中Manifest-Version的值,保留新版本的jar;
- 沒有MANIFEST.MF文件或沒有Manifest-Version鍵,取創建時間遲的jar;
設計完成了,實現部分我們留到下一篇繼續分享。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。