返回介绍

JDK 先生最近有点烦

发布于 2025-02-16 11:28:24 字数 4991 浏览 0 评论 0 收藏 0

1 JDK 先生有点烦

JDK 先生有点烦, 因为最近几个刺儿头程序经常找茬儿, 抱怨的还是 classpath, jar 文件, package 这几个 JDK 赖以生存、 引以为傲的基础设施。

想当年 java 诞生的时候, package 帮助程序员把 java 类更好地组织起来, jar 文件把 class 文件打成压缩包,而 classpath 这么多年一直兢兢业业地查找类文件,从来没出过差错。 为啥要抱怨他们呢?

前天用户系统跑过来说,他有两个 package ,com.foo.db.api.和 com.foo.db.impl, 他期望大家只使用 api 包的 UserDao, 可是总有一些不着调的程序员还去直接使用 impl 包,屡禁不止啊。

用户系统带着怨气地问道: 你就没有办法让 impl 包也变成对外私有的? 你要是再不支持,我们都要转到 OGSi 去了啊,到时候你后悔都来不及!

还有,昨天订票系统跑来说,他有两个模块,模块 A 依赖 json_1.1.jar,模块 B 依赖 json_2.0.jar , 可是这两个 jar 互不兼容, 怎么把它们放到 classpath 上?

JDK 觉得订票系统很变态,怎么会出现这样的代码,这不是自己折磨自己吗? 但转念一想,主要的问题还是自己的 classpath, 这个所谓的 classpath 是个平铺的线性结构, 而 jar 之间的依赖关系应该是个有向图啊!

今天还有个家伙说他要开发物联网应用, 内存受限, 他发现 JDK 和 JRE 太大了,动辄上百 M, 更要命的是其中有不少东西他们并不用, 例如界面相关的 jar , 但是又没法从 JDK 中去除。 能不能按照需要裁剪一下 JDK 呢?

如果说前面两个要求还算合理, 这个老兄的要求简直就是一场革命, JDK 自己革自己的命。

2 模块化

虽然 JDK 已经非常成熟,但是用户的需求不能置之不理。

JDK 闭关思考了半月, 终于憋出来一个大招:做粗粒度的模块化!

他把各位刺儿头招来商议。

“模块化? 还粗粒度? ” 一听到这个消息, 订单系统就跳了起来,生怕把自己给改乱了。

“是啊,模块一般指的是一个独立的单元, 它精确地声明了对外的接口和依赖。 你们想想,人类在开发中基本上都是把 jar 文件作为一个个的‘模块’, 每个 jar 文件中包含了一些 package , 但是 jar 文件本质上还是一堆.class 文件的压缩而已。”

“那该怎么办?” 用户系统好奇心被激发了,它特别想做 package 的权限控制。

“最简单的办法,可以在 jar 包中添加一个声明性的文件, 这个文件定义模块名,它对外提供的接口,和依赖, 像这样:”

用户系统很激动, 这简直就是为了他量身定做的: “嗯,这很容易理解, 这个 jar 的模块名叫做 com.foo.db, 依赖另外一个模块 java.sql , 这个 export 就是说别人只能访问 com.foo.db.api 这个 package 下面的类, 像 com.foo.db.impl 就不能访问了,对吧?”

com.foo.db.jar 文件的内容如下:

module-def.xml

com.foo.db.api.XXXX.class

com.foo.db.api.XXXX.class

......

com.foo.db.impl.XXXX.class

com.foo.db.impl.XXXX.class

......

JDK 赞许地说: “没错, 这就是所谓粗粒度的模块, 原来的 java class 也可以称为一个模块,但是粒度太细了, 现在我们把一组类封装到一个 jar 文件中,再加一个声明文件, 就变成了一个粗粒度模块。当然你肯定能想到,我自己也得做增强喽, 必须得能识别模块定义,并且正确的设置访问权限。”

用户系统说: “哎呀, 我其实最讨厌又臭又长的 xml 了, 能不能用 java 描述呢,就叫做 module-info.java 吧”

JDK 笑了: “看来你小子想得挺深的。 我也喜欢这样清爽的表达, 只不过得把 java 语法也增强了。增加像 module , requries, exports 这样的关键字才行。”

现在: com.foo.db.jar 文件的内容如下:

module-info.class

com.foo.db.api.XXXX

com.foo.db.api.XXXX

......

com.foo.db.impl.XXXX

com.foo.db.impl.XXXX

......

3 JDK 自身的革命

开发物联网的小伙子问道: “JDK 先生, 你自己是不是也要搞成模块化啊 , 这样我就可以裁剪出我使用的模块了。”

“是啊, 你们上层要是模块化了, 我肯定也得这么搞,并且我还得先搞出来, 这样你们好使用啊。这对我来说,是一场巨大的革命啊, 我得把我成千上万的类给捋一捋,形成层次分明,隔离良好的模块, 我现在才总结了一部分: java.desktop , java.xml, java.sql , java.naming, java.logging, java.scripting......”

订单系统打断说: "慢着, 难道让我在每个模块中都导入所有的 JDK 的基本模块吗? 这不把人给累死?"

JDK 说: “不不, 这个问题我也考虑过了,其实可以引入一个隐式的依赖嘛, 我把 JDK 中最重要的核心模块组织起来,形成一个 java.base 模块,其他模块都隐式的依赖它就行了, 就像你的 java 类不用 extend Object 一样, JDK 会自动给你加上。”

4 迁移

用户系统说: “ 模块化的想法很不错, 解决了我的问题。 可是现有的大部分程序和 jar 包都没有实现模块化, 单单自己实现模块化有什么用, 你去 require 谁? 你 export 出去的接口被谁用? ”

大家都向用户系统投来了佩服的目光, 这是个非常现实的问题。

模块化仅仅有 JDK 的改变还不够, 除非大家都用起来,要不然还是无法实施。

log4j 跳出说: “是啊是啊, 你们都迁移成模块了, 我一直没改,该怎么办?”

JDK 说: “ log4j 你不用担心, 肯定得有一种让大家慢慢迁移到‘模块’的路径才行, 就说你吧, 还没有模块化,但是用户系统想拥抱模块化, 他要 require 你,该怎么办?”

“也许我可以临时的给他们起个名字,例如 log4j-module , 可是我的模块怎么才能知道这个'临时模块'的存在呢?” 用户系统说

“想想 classpath , 我们可以搞个 modulepath , 只要加入到这个 modulepath 的 jar 文件,例如 log4j.jar , 就自动认为这是一个 module (虽然他没有 module-info.java 声明) , 这样你就可以 requrie log4j 来使用它了。”

"妙啊,这可以让大家慢慢的迁移, 我可以先把我的应用转化为模块 , 如果哪个类库还没拥抱模块化, 我就把它放到 modulepath 中,让它自动成为一个模块, 这样我就可以 require 了!"

用户系统对 JDK 的方法非常佩服。

“别高兴的太早” JDK 说, “一个类库一旦成为自动的模快, 那它就能访问所有的模块,因为我们不知道它到底依赖谁, 为了能让大家迁移到模块化,这也算是一个代价吧。 ”

“对了,要是只有 JDK 实现了模块化, 但是我们上层的应用还没有开始迁移, 能在新的 JDK 上运行吗? ” 订单系统担忧的问道。

“那必须得运行,不是自夸,我比较牛的一点就是向后兼容性, 早期的代码甚至不用修改就可以在最新的 JRE 上运行, 新的特性可不能破坏这种兼容性!”

“那该怎么搞? ”

“很简单, 我会把所有这些没有迁移的类库都放置到一个叫做 unnamed 模块当中, 这样概念上就统一了。 ”

“不错不错, 听起来可行” 大家纷纷表示赞成 “要不试一试?”

“心急吃不了热豆腐, 我今天召集大家来也是把主要的想法给大家分享下, 说起来简单, 里边有很多细节我得好好想想才行, 大家耐心地等待下一个版本的发行吧!”

后记 : 本文介绍的就是 Java9 的新特性: 模块化的一些概念, 还有很多其他的细节,感兴趣的同学可以点击阅读原文去 openjdk 的网站上去看看 。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文