写点什么

Jigsaw 项目会解决 Java 的 JAR 地狱问题么?

  • 2015-12-31
  • 本文字数:2011 字

    阅读完需:约 7 分钟

Nicolai Parlog 是一位热情的软件工程师,数字版权与开源软件的狂热拥护者;他对 AssertJ、ControlsFX、FindBugs 及 Property Alliance 等项目都做出过重要的贡献。近日,Parlog 就 Jigsaw 项目撰写了一篇文章,谈到了 Jigsaw 项目的一些不足以及改进之处。Jigsaw 项目有着雄心勃勃的宏伟目标,其目标之一就是彻底摆脱极易出错且问题多多的类路径机制中的 JAR 地狱问题。不过,虽然该项目的其他目标会在不久的将来得以实现,但解决 JAR 地狱问题这一目标似乎并不是那么容易的。

为了更好地理解我们接下来要讨论的内容,首先来看一下 JAR 地狱问题,接下来介绍 Jigsaw 项目将会解决问题的哪些方面,以及为什么说 Jigsaw 所尝试解决的问题并不会对整个问题域产生本质的影响。最后,我们来看一下官方对于这个话题的立场,并给出如何防止出现模块地狱的提案。

JAR 地狱问题

JAR 地狱存在着如下循环问题:

  • 表述不清以及传递性依赖
  • 遮蔽
  • 版本冲突
  • 复杂的类加载

根据构建工具与组件系统(JDK 开发者称之为容器)为我们所带来的诸多功能与特性,我们可以认为表述不清以及传递性依赖问题已经在很大程度上得到了解决,遮蔽问题至少得到了缓解,而复杂的类加载也不再是老生常谈的问题了。这样,版本冲突就成为 JAR 地狱中最为严重的一个问题了,它影响到了很多很多项目每天的更新决策。

Jigsaw 将会带来哪些改变?

我之前曾就 Jigsaw 项目会为 Java 9 带来哪些新特性专门写过文章进行过介绍,不过这里将从不同的视角进行阐述。首先,它会受到当前的早期访问构建版的影响;其次,我们这里只从与 JAR/ 模块地狱相关的角度进行介绍。

Jigsaw 为 Java 带来的核心概念就是模块化。简而言之,模块就像 JAR 一样,同时带有一些附加信息与特性。这些信息包含了模块的名字以及模块所依赖的其他模块的名字。

依赖

当编译器与 JVM 在处理模块时,他们会解析这些信息。在编译或启动时,他们会通过模块路径传递性解析所有依赖。总体来说,这类似于类路径扫描,不过现在寻找的是整个模块而非单个类,对于 JVM 来说,这是在启动期而非运行期进行的。如果在模块路径上无法找到所有依赖,那么解析模块的传递性依赖就会失败。这显然可以解决表述不清,以及无休止的传递性依赖的问题。我认为这是个很棒的做法,Java 语言现在正式知道关于依赖的信息了,所有工具(编译器与 JVM 等)都能理解这一点并正常使用!不过,我认为这并不会对开发者每天的工作产生多少积极的影响,因为现在很多既有的基础设施都已经解决这个问题了,比如说构建工具等。

遮蔽

Jigsaw 消除了遮蔽的问题。模块系统可以确保每个依赖都会被另一个模块所实现,每个模块都会读取至多一个模块,定义了同名包的模块之间并不会相互干扰。更准确地说,模块系统在遇到模糊不清的情况时就会终止并报错,比如说两个模块将相同的包导出到相同模块中。

版本冲突

我们认为第三方库的版本冲突是 JAR 地狱最为难以解决的问题。最直接的解决方案就是一个模块系统能够加载同一个模块的不同版本。这需要确保这些版本之间不存在互相交互的情况。问题在于:在单个配置中,没必要支持一个模块的多个版本。实际上,当前的构建既不会创建,也无法理解模块版本信息。曾有人使用了一些变通办法。最丑陋,同时也是最可行的办法就是重命名出现冲突的构件,这样他们就不再是相同模块的两个不同版本了,而是两个完全不同的模块。不过,这种做法最后证明也是行不通的。显然,确保“定义了同名包的模块之间不会相互干扰”是在两个模块导出相同包时拒绝任何启动配置来实现的。即便没有模块读取他们亦如此!

复杂的类加载

模块与类加载器之间如何交互以及如何改变类加载的复杂性是个很棘手的问题。实际上,模块系统对模块与类加载器之间的关系并没有做多少限制。类加载器可以从一个模块或是多个模块来加载类型,只要模块之间不存在相互干扰的情况,并且每个模块中的类型只由一个加载器加载即可。因此,类加载器与模块之间是一对多的关系。

模块地狱?

既然依赖与遮蔽问题已经得到了解决,并且类加载问题也得到了改进,那我为何还要讨论模块地狱呢?就是因为版本冲突么?没错!如果 Jigsaw 想要解决 JAR 地狱问题,它就需要特别注意版本冲突问题。否则,很多项目并不会出现什么起色。他们依然要面对版本冲突问题,并且会陷入到自定义类加载器的梦魇中。

提案

我的提案是让开发者与构建工具能够传递一些额外的信息,这些信息能够解决一些含糊不清的问题。传递这种信息的两种常见方式是命令行与配置文件。如果使用命令行参数,那么每次启动时都需要输入一次。根据信息的多少以及项目的规模,这种做法可能会变得非常乏味。可以通过构建工具来创建配置文件,然后再通过命令行指定配置文件。这看起来是个不错的解决方案。目前,初始模块与所有的传递性依赖都是通过单个配置来解析的,这形成了单独的一个层次。不过,我们可以在运行期将相同模块的多个版本加载到不同层次中,这正是组件系统要做的事情。总的来说,我的建议就是通过多个层次来显式指定配置。

2015-12-31 02:122773
用户头像

发布了 88 篇内容, 共 272.3 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

redhat运维-ftp服务故障

阿柠xn

Linux 运维 ftp 11月月更

Linux系统保存文件命令的详细介绍

源字节1号

软件开发 前端开发 后端开发 小程序开发

vue实战中的一些小技巧

yyds2026

Vue

手撕常见JS面试题

helloworld1024fd

JavaScript

记一次京东前端面试被问到的题目

helloworld1024fd

JavaScript

数据结构学习笔记(二)

lxmoe

数据结构 学习笔记 11月月更

React Context源码是怎么实现的呢

flyzz177

React

Wallys/IPQ4018/IPQ4028 2x2 2.4Ghz 2x2 5Ghz Industrial WIFI5 router/Support 11ABGN/AC

Cindy-wallys

IPQ4018 IPQ4028 2.4G&5G

python中类与对象的动态性,混入机制

乔乔

11月月更

vue实战-完全掌握Vue自定义指令

yyds2026

Vue

腾讯前端高频手写面试题

helloworld1024fd

JavaScript

企业级 Angular 应用路由路径自定义配置和开发的案例分享

汪子熙

typescript 前端开发 angular Web应用 11月月更

zabbix添加自定义监控项&告警(邮件)

A-刘晨阳

Linux 运维 zabbix 11月月更

HarmonyOS 3.1版本发布,全面进入声明式开发

HarmonyOS开发者

HarmonyOS

用了8年MQ!聊聊消息队列的技术选型,哪个最香!

小小怪下士

Java RocketMQ RabbitMQ 消息队列

算法基础:离散化及模板详解

timerring

算法 11月月更 离散化

Wallys/ DR9074-6E QCN9074 WIFI 6E 802.11AX 4X4 6GHz/ industrial M.2 card / DR9074-6E(PN02.7)

Cindy-wallys

m.2 QCN9074 WIFI 6e

产品待办列表PBL与产品需求文档PRD的本质区别

ShineScrum

Scrum PRD 产品待办列表 PBL 产品需求文档

关于软件物料清单(SBOM),你所需要了解的一切

SEAL安全

安全 软件物料清单 SBOM

细说react源码中的合成事件

flyzz177

React

Java中的BigDecimal比较大于小于等于,四舍五入保留几位(setScale方法详解),加减乘除取余

共饮一杯无

Java BigDecimal 11月月更

【docker】导入镜像报错磁盘空间不足的解决方法 && 【docker】修改默认的存储路径

A-刘晨阳

Docker Linux 运维 11月月更

数据结构学习笔记(一)

lxmoe

数据结构 学习笔记 11月月更

Linux系统中CPU占用率较高问题排查思路与解决方法

A-刘晨阳

Linux 运维 cpu 11月月更

荣耀开发者大会预约有礼

荣耀开发者服务平台

开发者 手机 开发者大会 荣耀 honor

Apache Pulsar 社区年度峰会 Pulsar Summit Asia 2022 即将召开

腾源会

大数据 开源

浅谈HTTP缓存与CDN缓存的那点事

京东科技开发者

缓存 性能 Web CDN HTTP缓存

ElasticSearch深度分页详解

京东科技开发者

数据库 elasticsearch 分布式搜索引擎 分布式实时搜索引擎

vue实战-深入响应式数据原理

yyds2026

Vue

ReactDOM.render在react源码中执行之后发生了什么?

flyzz177

React

能否手写vue3响应式原理-面试进阶

helloworld1024fd

JavaScript

Jigsaw项目会解决Java的JAR地狱问题么?_Java_张龙_InfoQ精选文章