- 大话编程
- 一个故事讲完 https
- C 老头和 Java 小子的硬盘夜话
- 我是一个函数
- 操作系统是个大骗子?
- 90 后 老头儿 和 00 后 Go 小子的硬盘夜话
- 爱炫耀的数据库老头儿
- 浏览器:一个家族的奋斗
- 浏览器家族的安全反击战
- 黑客三兄弟
- 从读写分离到 CQRS,张大胖是如何解决性能问题的?
- 两个程序的爱情故事
- 两个程序的爱情故事(续)
- 烂代码传奇
- 机房夜话
- 干掉状态:从 session 到 token
- 张大胖的 docker 之路
- 从 SOA 到微服务
- XML 的传奇人生
- 从密码到 token, 一个授权的故事
- 编程世界的那把锁
- 加锁还是不加锁,这是一个问题
- 这个动物园, 两年也逛不完
- 张大胖和 CAP 定理
- 一个翻译家族的发家史
- 张大胖和单元测试
- Java 帝国
- 一个著名的日志系统是怎么设计出来的?
- Java 帝国之泛型
- Java 帝国之动态代理
- 从兄弟到父子:动态代理在民间是怎么玩的?
- Java 注解是怎么成功上位的?
- Java EE 要死掉了?
- Java 帝国之宫廷内斗
- Java 帝国之宫廷内斗(2)
- 当世界上只剩下一个 Java 程序员
- 持久化:Java 帝国反击战
- 什么是框架?
- 学习 Java 虚拟机没用? 听听当事人是怎么说的!
- 聊聊 Java 平台上的非 Java 语言
- Java 帝国之消息队列
- Java 帝国之 JMS 的诞生
- Java 帝国之单例设计模式
- 对 Java Inputstream 的一次采访
- ASM: 一个低调成功者的自述
- 序列化: 一个老家伙的咸鱼翻身
- Java IO 的自述
- JDK 先生最近有点烦
- 什么是框架(续)?
- 说 空话,做实事: 谈谈多态
- Kotlin 初体验
- 小白科普
- 小白科普:分布式和集群
- 什么是 Zookeeper?
- 小白科普:悲观锁和乐观锁
- 小白科普:LDAP 有什么用?
- 小白科普:服务那点事儿
- 小白科普:Netty 有什么用?
- 老司机经验
- 后端程序员都做些什么?
- 为什么要学习 HashMap 的底层原理?
- 小心,别被今日头条给困住了!
- 对自己狠一点,开始写作吧
- 开源代码啃不动,不如先定个小目标
- Python 这么简单还用学吗?
- 作为一个有追求的程序员,你应该掌握的七种武器
- 给设计模式说句公道话
- 时间是这么被浪费掉的
- 你真正付出了全部努力了吗?
- 写给初学者:编程的本质
- 在大学期间更应该学习什么?
- 看看 悲催 的码农得学多少东西?
- 学习编程的四兄弟
- 那些年,我后悔没做好的事情
- 我为什么对后端编程情有独钟?
- 当我们在学习编程语言时,我们在学习什么?
- 编程需要多少数学知识?
- 想成为编程高手,一定要学汇编吗?
- 你必须理解的计算机核心概念
- 你的需求是怎么描述的?
- 白话敏捷软件开发
- 人在职场
- 凡事必先骑上虎背,给性格内向的程序员聊几句
- 为什么能力优秀的人当了主管以后反而不行了呢?
- 不想做技术了,还有一条路
- 纪念我最有效率的一次加班
- 书写「简历」时,需要规避的错误。
- 上天还是入地?
- 工作 6 年,半路出家到 CTO
- 只是 Work 还不够,更重要的是 Think
- 我所尊敬的三位女程序员
- 我们向印度人学习什么?
- 你去下家面试,怎么评价你在这家公司做的工作?
JDK 先生最近有点烦
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论