Executable Jar、Fat Jar、Uber Jar

在 Java 中,如果要运行 Java 程序,需要一个包含 main 方法类的 jar 包或类文件,然后执行命令:

#Run a class file
java $class

#Run a java package (main class specified in manifest)
java -jar $jarfile

#Run the main method of a class, and add multiple jar packages to the classpath of the runtime
java -cp (- classpath) $path (directory/jar file /zip file) # zip file should conform to the specification of jar format

这种方法会有一些缺点,因为大多数 Java 程序都包含很多依赖项。如果要启动此程序,必须传递 classpath 以指定这些依赖的包文件,并且必须在服务器上指定类路径,这不是很方便,特别是随着 DevOps/Microservices 的普及,这种指定 classpath 的方法过于死板。我们可以直接构建聚合的 jar 包并发布或运行它。

Executable Jar

可执行 jar 包通常意味着所有依赖的 jar 包都放在一个大的入口 jar 包中。这个入口 jar 包中包含运行时需要依赖的所有 jar 包和类文件。您可以将依赖的 jar 包直接放在入口 jar 包中,如下所示:

├─executable jar
│  ├─META-INF
│  │  ├─MANIFEST.MF
│  ├─com...
│  ├─lib
│  │  ├─io.netty....jar
│  │  ├─com.google....jar
│  │  ├─com.github....jar
│  │  ├─org.apache.....jar

您还可以将依赖的 jar 包中的文件复制到入口 jar 包中,如下所示:

├─executable jar
│  ├─META-INF
│  │  ├─MANIFEST.MF
│  ├─com...
│  ├─io.netty.... classes
│  ├─com.google.. classes
│  ├─com.github.. classes
│  ├─org.apache.. classes

Spring Boot 打出的 jar 包可以被看作是一个可执行 jar。Spring Boot 在 spring-boot-maven-plugin 插件可以在构建过程中将所有依赖的 jar 包打包成一个入口 jar 文件,并通过 Spring Boot 的类加载器和启动类来将这些依赖 jar 包加载到可执行的入口 jar 包中,上面描述的第一种方法是:将依赖的 jar 包直接放进入口 jar 包中。

Uber Jar

当我第一次看到这个词时,我不知所措。我不知道这个词是什么意思。优步出租车?查找信息后,我发现 Uber jar 的原始单词是 Über jar,是一个德语单词,可以解释为 over 或 end,但在实际上下文中,将其翻译为 everything 可能更合适。

这个术语最初是由开发人员创造的,他们认为将所有依赖项和自己的代码放入 jar 文件可以解决许多冲突。但大多数输入法很难输入 Ü,所以被称为 Uber。

Fat jar

Fat jar 是对 fat 和 big 的一个很好的解释:Fat jar 和 Uber jar 表示包含所有依赖包的 jar 包。

Shade jar/Shadow jar

Shade jar 就是将依赖包也打包到入口 jar 包的 jar 包,并提供对某些依赖包进行重命名的功能。例如,一个 Maven 项目依赖于许多第三方软件包,但您希望在实际打包期间重命名一些软件包。重命名的过程在这里可以称为 Shade(着色)。

为什么要重命名依赖包呢?例如,当我们开发时还需要依赖一些第三方软件包,比如 netty,所以我们需要在实际操作中以 –javaagent 或动态附加 jar 包的形式加载我们的代理 jar 包。这里加载的代理只能是一个独立的 jar 包,因此首先,我们需要通过在 jar 包中键入我们的代理及其依赖包来构建一个 Uber jar。然后,我们需要考虑类包冲突的问题,因为代理中的依赖包类和目标 JVM 进程中的类可能会发生冲突,例如,代理依赖于 netty 4.1.58.final,而目标 JVM 进程依赖于 netty 4.0.14.final,我们的代理使用 4.0.14 中不存在的 API。此时,程序将产生找不到方法的异常,因为目标进程已加载该类,并且不会重复加载代理程序包中具有相同全限定名的类。

在构建 Uber jar 时,可以修改并重新定位依赖包的包名,这比下载项目的源代码重构包名再打包要方便的多。比如,将 io.netty 修改为 com.github.kongwu.io.netty,同时,Java 代码中的所有引用在重新定位后都使用被修改后的包名。这样,通过修改包名,完全避免了依赖性包类冲突的问题。Google 也开源了一个类似功能的 jar 文件,叫做 jarjar.jar(好多 jar 啊)。

上述 relocation 行为称为 Shade 或 Shadow。Maven 中的 Shade 插件可以将程序打包到单独的jar包中,包括依赖项包。另一个类似的 Maven Assembly 插件也可以达到同样的效果。Gradle 中也有类似的插件,功能也很强大,也支持 Shade 功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容