课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
java编程语言算是目前使用最广泛的编程语言之一了,而2017年将要推出最新的java9,可以说是java发展史上的又一次技术升级迭代,那么在新的java技术之下,它与以前的版本有什么不同呢?
今天,我们主要就java最新的升级之后的技术来一起了解一下,最新java编程语言的发展。
Java 9将在2017年发布,一个标志性的特性是新的模块化系统,命名为Java平台模块化系统(JPMS)。本文探讨了它与现有的Java标准组件如何关联起来,以及它对现有的Java标准组件有什么影响。
自1.0版本以来,Java已经增长了20倍,模块化平台是非常必要的。为了解决这个问题,也曾有过很多失败的尝试。而与此同时,OSGi已经提供应用程序模块化16年。
OSGi和JPMS在实现细节上有本质上的区别。如果JPMS被当作模块化的通用解决方案,似乎会有严重的缺陷和缺失的功能。
JPMS的目标是使用起来比OSGi更简单、更容易。但是,让现有的非模块化产品模块化是非常复杂的,而且JPMS在这个目标上似乎没有成功。
JPMS在Java平台自身模块化方面做得很好,这意味着我们可以为特定的工作构建一个小的运行时环境,它只包含Java平台相关的部分。在应用程序模块化方面OSGi有很多优势。我们已经证明了两者可以结合起来,这看起来是一个成功的方式。
Java 9将在明年发布,一个标志性的特性是新的模块化系统:Java平台模块化系统(JPMS)。虽然JPMS的细节还没有完全确定,我们已经了解了很多有关它方向性的内容。
Java已经有一个预先存在的模块化系统,自2000年以来一直以各种形式存在。它就是被称为OSGi的模块化系统,是一个独立于供应商的行业标准。它由OSGi联盟发布,由领先的软件供应商、电信公司和其他组织(包括Adobe、博世、华为、IBM、Liferay、NTT、Oracle、Paremus 以及Software AG)组成。它推进了几乎所有的Java EE应用服务器、最流行的IDE、Web应用程序(像eBay、#和Liferay),并用于政府和军队,如美国空军和联邦航空管理局。
OSGi是为物联网提供的——OSGi一开始是专为嵌入式设备设计的,那是在很多年前,当时内存和CPU资源明显受到局限。现在设备有了更多的能力。这提供了构建复杂应用程序和解决方案的机会,并催生了蓬勃发展的生态系统,在这个生态系统中组织和个人贡献的软件和硬件元素可以添加到整体解决方案中。这样的生态系统在市场上很广泛,包括互联家庭、车联网、智能城市和工业4.0(IIoT)。网关通常用于传感器和设备之间相互连接,并连接到后端系统。应用程序和服务可以在本地网关和/或云上运行。
OSGi还提供多种规范启用构建开放的物联网生态系统的基本特性。这些特性包括设备管理、软件配置以及设备抽象,即从底层通信协议归纳设备。在今天,像AT&T、博世、NTT、德国电信、美国通用电气、日立、美诺、施耐德电气等公司都受益于采用OSGi构建物联网的解决方案,并且做了很多年。目前已经有上百万的设备连接采用OSGi和物联网。
当然,OSGi的用户都很好奇Java 9中新的模块化系统在短期和长期将会如何影响OSGi。
Java生态系统中很快会出现两个模块化系统,这有技术、政治和商业的原因。本文中,我们避开政治原因,从技术的角度对两者进行比较。我们总结了JPMS和OSGi如何协同工作,思考它们各自的领域是什么以及在崭新的世界中存在什么样的机遇。
请注意,本文中,我们使用的信息在2016年8月已公开发布。在该规范确定之前一些细节可能会改变。
背景
自1990年代末诞生以来Java平台增长显著。综观下载文件的大小,JDK 1.1为10Mb,而Mac OS X下载JDK 8u77却非常大,有227Mb。安装占用的空间和内存需求也有了相应的增加。这些增加是因为增加了新的功能,而且大部分功能是受欢迎并且有用的。然而,每一个新的功能都为不需要这个功能的用户创造了膨胀——没有人会使用平台所有的功能。而且即使已经过时,所有现有的功能都会保留,因为Java管理员提供了令人钦佩的奉献精神——向后兼容性。
多年来,Java体重的增加并不是一个大问题。它是最流行的企业平台,它的主要竞争对手是微软的.NET,然而.NET也有着相似的轨迹。在当今世界,Java面临不同的挑战。物联网推动了空间占用新一轮的关注,新的、灵活的平台和语言(比如Node.js、Go)都是非常有竞争力的对手。
安全也是一个大问题:Java攻击引起了组织对安全意识的重视,把它从用户桌面完全移除。如果内部JVM和用户空间应用程序代码之间有更好的隔离,这些攻击是不可能发生的。
很早之前我们就清楚需要为模块化平台做一些事情了。在2000年中期有一系列失败的尝试,例如,JSR 294和它的“superpackages”,JSR 277的“Java模块化系统”——最终名为Jigsaw的原型项目出现了。这本来是在2011年Java 7中提交的,但被推迟到Java 8再推迟到Java 9。作为一个原型项目,Jigsaw为JPMS规范提供了参考实现。
而与此同时,OSGi用了16年时间不断发展和完善。OSGi是应用程序模块化的标准:由于它不是Java平台的一部分,它不能影响平台本身的模块化。但是,许多应用已经受益于它提供的高于JVM的模块化模型。
高层比较
JPMS和OSGi之间有很多小的差异,但是有一个很大的不同,就是隔离的实现。
隔离是模块化系统最基本的特征。每个模块必须有一些保护措施防止运行在同一应用程序中其他模块的干扰。隔离是一个连续的而不是二进制的概念:无论OSGi还是JPMS都需要做一些事情来避免那些表现不好的模块的影响,这些模块占用了JVM中所有可用的内存,运行了数千个线程或者让CPU处于繁忙的循环。如果一个模块可以作为操作系统上独立的进程运行,是可以提供这类保护的,但即使是这样,它也是不完美的;有人仍然可以使操作系统崩溃或者擦除磁盘。
OSGi和JPMS都提供了代码级隔离,这意味着一个模块不能访问另一个模块的内部类型,除非该模块有明确的许可。
OSGi通过类加载器实现隔离。每个模块(或者在OSGi术语中称为“bundle”)有一个类加载器,它知道如何在bundle中加载类型。它也可以将类加载请求委托给它所依赖的其他bundle的加载器。该系统是高度优化的,例如,OSGi不会为一个bundle创建一个类加载器直到最后一刻,而且事实上每个加载器会处理一个更小的类型,这样每个类型可以加载得更快。
这个系统最大的优势是,bundle可以包含重叠的包和类型,而且不会相互干扰。实际的结果是,可能某些包和库有多个版本同时运行在相同的JVM。在处理像Maven这样的构建工具带来的复杂的传递依赖图时,这是个福音。在许多企业,Java应用程序几乎不可能有这样的一套依赖,该依赖中每个库只包含一个版本。
例如,我们来看看 JitWatch 库 1 。JitWatch依赖于 slf4j-api 1.7.7 和 logback-classic 1.1.2,但是logback-classic 1.1.2依赖于slf4j-api 1.7.6,与JitWatch直接的依赖有冲突。JitWatch也传递地依赖于 jansi 1.6和1.9版本,如果包含测试范围的依赖,我们会有另一个slf4j-api的版本1.6。这种混乱是很常见的,传统的Java中没有真正的解决方案,只能逐步在依赖树中添加“excludes”直到奇迹般地得到一套可以运行的依赖库。不幸的是对于这个问题JPMS也没有答案,我们很快就会看到。
使用类加载器进行隔离确实有一个缺点:它打破了每一个类型最多可以在一个位置找到的假设。这是模块化的一个自然结果。如果一个模块可以不受其他模块的干扰使用自己的类型,那么不可避免地一个单一类型的名称可能会在多个模块中发现。遗憾的是,这造成了一个问题,因为很多保留的Java代码不是用模块化的思想编写的。特别是,调用Class.forName(String)通过名字查询类型时,在真正模块化的环境中不是总能得到正确的结果,因为有多个可能的返回类型。
正是由于这个缺点,不能使用OSGi模块化JDK本身。JDK的许多地方都有一个隐含的假设,任何JDK类型可以从JDK的任何其他部分加载,所以很多事情在OSGi下会被打破,比如模型。为了解决这个问题,也为了减少使用Class.forName代码的迁移,JPMS选择在隔离时不使用类加载器。当你在“modulepath”使用一组模块来启动应用程序时,所有这些模块将由相同的类加载器加载。相反,JPMS引入新的访问规则实现隔离。
OSGi的隔离屏障是 可见的 。在OSGi,我们不能加载一个模块的内部类,因为它们是不可见的。也就是说,自己模块的类加载器只能看到自己模块内部的类型以及从其他模块明确导入的类型。如果我试图从其他的模块中加载一个内部类,我的类加载器是看不到该类型的。就好像是根本不存在的类型。如果试图继续加载该类,就会得到NoClassDefFoundError或者ClassNotFoundException的异常。
在JPMS,每一个类型对于任何其他类型都是可见的,因为他们存在于同一个类加载器。但是,JPMS增加了辅助检查以确定加载类有权访问它试图加载的类型。其他模块的内部类型实际上是private的,即使它们被声明为public。如果我们试图继续加载它,那么我们会得到IllegalAccessError或者IllegalAccessException的异常。如果我们试图加载private的或者另一个包的默认访问类型也会得到相同的错误,而且在这个类型上调用setAccessible也是无用的。这改变了Java中public修饰符的语义,以前它是普遍可访问的,现在只可在一个模块和它的require对象中访问。
JPMS方法的缺点是,它不可能有重叠内容的模块。也就是说,如果两个模块都包含一个私有(非导出)的包org.example.util,这些模块不能同时在模块路径上被加载——它会导致layerinstantiationexception异常。通过应用程序实例化类加载器可能会解决此限制——但这正是OSGi已经为我们做的!
再次强调,完全是通过设计允许JPMS模块化JDK的内部。但结果是,你会有不能完全一起工作的模块,因为它们内部的实现细节有冲突。
达内时代科技集团致力于培养面向电信和金融领域的Java、C++、C#/.Net、3G/Android、3G/IOS、PHP、嵌入式、软件测试、UID、网络营销、网络工程、会计、UED、web、Unity3D、大数据、童程童美等17大方向中高端软件人才课程与少儿教育课程。选择运城电脑培训,不再孤军奋战,轻轻松松做IT高薪白领。运城达内培训带领有明确目标的学子迈向成功之路!想找工作的求职者可以加QQ:3373924515(太原达内就业服务部)咨询了解。