阿里Java架構師打包 FatJar 方法小結

jar-with-dependencies

3. 嵌套方法(Jar of Jars)

還是一種辦法就是在 jar 包裡嵌套其他 jar,這個方法可以徹底避免解壓同名覆蓋的問題,但是這個方法不被 JVM 原生支持,因為 JDK 提供的 ClassLoader 僅支持裝載嵌套 jar 包的 class 文件。所以這種方法需要自定義 ClassLoader 以支持嵌套 jar。

Onejar Maven Plugin

One-JAR 就是一個基於上面嵌套 jar 實現的工具。onejar-maven-plugin 是社區基於 onejar 實現的 maven 插件。

com.jolira

onejar-maven-plugin

1.4.4

one-jar

Spring boot plugin

One-JAR 有點年久失修,好久沒有維護了,Spring Boot 提供的 Maven Plugin 也可以打包 Fatjar,支持非遮蔽和嵌套的混合模式,並且支持 maven 和 gradle 。

org.springframework.boot

spring-boot-maven-plugin

ZIP

org.jruby

jruby-complete

plugins {

id 'org.springframework.boot' version '2.0.4.RELEASE'

}

bootJar {

requiresUnpack '**/jruby-complete-*.jar'

}

requiresUnpack 參數可以定製那些 jar 不希望被解壓,採用嵌套的方式打包到 Fatjar 內部。

其打包後的內部結構為

example.jar

|

+-META-INF

| +-MANIFEST.MF

+-org

| +-springframework

| +-boot

| +-loader

| +-

+-BOOT-INF

+-classes

| +-mycompany

| +-project

| +-YourClasses.class

+-lib

+-dependency1.jar

+-dependency2.jar

應用的類文件被放置到 BOOT-INF/classes 目錄,依賴包被放置到 BOOT-INF/lib 目錄。

查看 META-INF/MANIFEST.MF 文件,其內容為

Main-Class: org.springframework.boot.loader.JarLauncher

Start-Class: com.mycompany.project.MyApplication

啟動類是固定的 org.springframework.boot.loader.JarLauncher,應用程序的入口類需要配置成 Start-Class。這樣做的目的主要是為了支持嵌套 jar 包的類裝載,替換掉默認的 ClassLoader。

但是函數計算 Java Runtime 需要的 jar 包是一種打包結構,在服務端運行時會解壓開,./lib 目錄加到 classpath 中,單不會調用 Main-Class。所以自定義 ClassLoader 是不生效的,所以不要使用嵌套 jar 結構,除非在入口函數指定重新定義 ClassLoader 或者 classpath 以支持 BOOT-INF/classes 和 BOOT-INF/lib 這樣的定製化的類路徑。

小結

阿里Java架構師打包 FatJar 方法小結

單從 Fatjar 的角度看, Spring boot maven/gradle 做得最精緻。但是 jar 包內部的自定義路徑解壓開以後和函數計算是不兼容的。所以如果用於函數計算打包,建議使用 Unshaded 或者 Shared 的打包方式,但是需要自己注意文件覆蓋問題。

寫在最後:歡迎留言討論,私信“Java”或“架構資料”有驚喜喲!加關注,持續更新!!!


分享到:


相關文章: