阿里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”或“架构资料”有惊喜哟!加关注,持续更新!!!


分享到:


相關文章: