查看原文
其他

JDK先生最近有点烦

2017-06-27 老刘 码农翻身
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 的网站上去看看 。 


你看到的只是冰山一角, 更多精彩文章,请移步《码农翻身文章精华


有心得想和大家分享? 欢迎投稿 ! 我的联系方式:微信:liuxinlehan  QQ: 3340792577



码农翻身

用故事讲述技术本质

微信号:coderising


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存