本文共 6151 字,大约阅读时间需要 20 分钟。
2017年9月Java9正式发布,之前就一直听说新版会有模块化,仔细了解下Java9的发展史,这个模块化确实比较坎坷,当然,好事多磨嘛。
1、相关组织
JUG:Java User Groups(Java用户群),以下是JUG官方提供的组织列表,其中有两个是大陆的,一个在南京,一个在杭州,个人感觉南京的现在不怎么活跃了,之前在南京时参加过南京JUG组织的活动。杭州的JUG应该我们公司的同学比较多吧。
JCP:Java Community Process,一个促进Java发展的国际组织,主要负责JSR的制定,OpenJDK的开发。其中JUG属于JCP。
EC:Executive Committee,是JCP中的执行委员会,是选举产生的,但Oracle是终身的执行委员会(没办法,因为JCP也是由SUN(后被Oracle并了)发起的),主要负责JSR的制定,有投票权。这里列一下曾经的EC成员:Motorola、Nokia、Sony、Samsung、HP、Siemens、Texas Instruments、Apple、Philips、Symbian、JBoss、Google、Ericsson、BenQ、SpringSource、AT&T、VMWare、Aplix、Freescale、Apache、Doug Lea、Timothy Peierls。
2、相关名词
JEP:JDK Enhancement Proposals(JDK增强建议),来源于JCP社区,但不一定被采纳,如果
JSR:Java Specification Requests(Java规范请求),JSR是有状态的,并不是所有的JSR都有效,所以在看JSR时需要先看下状态是否有效。Java的各个版本的语言规范和虚拟机规范都是JSR范畴里的,JSR的生效由Expert Group(专家组)商讨制定并由EC投票确立。JSR的确立是有一个具体流程规范的,不过并不是所有的JSR都会在JDK里实现的。
JSR专家组(Expert Group):从JCP里选出的对应领域有威望的个人(其实背后代表的是所属公司),负责制定和修改JSR。其中Java9对应的JSR379的专家组如下:
Java语言规范:其实已经包括在JSR里,细分开是因为只是语言层面的,不涉及跨平台的JVM的细节,所以想要详细了解Java语法的可以仔细研读下。具体代码里如何实现的不在规范里。
JVM规范:这里主要描述虚拟机的实现规范,包括指令集及期作用、虚拟机内存模型、类文件描述、编译、链接、加载、初始化等步聚描述,想要了解虚拟机具体是怎么工作的可以仔细研读下,不过规范不涉及实现,目前虚拟机的实现也有很多种,HotSpot是OpenJDK里的,想要了解实现细节的可以下载HotSpot源码看下。
3、JDK功能的由来
通过上面的一些简介可以大致看出,JDK的功能来源于Java开发者在实际使用时发现的一些不足之处,然后以JEP的方式反馈给社区,社区再通过专家组收集并制定JSR,再由EC投票是否要采纳,对于规划到Java版本JSR里的再由JCP分配或认领开发实现,经过一系列测试验证后发布Release版本。
4、
Java9的规范是JSR379,但379又依赖JSR376,也就是Java的平台模块化,在JDK9的源码里也可以看到“@spec JPMS”,这个表示的是这块代码是JSR376里要求实现或修改的。
5、涉及哪些JEP?
个人根据JSR文档整理了下,共涉及91个JEP,其中8个JEP是关于废弃的,39个JEP是关于修改的,44个JEP是关于新增的,模块化涉及8个JEP,安全涉及7个JEP。可以看出Java9不仅仅是模块化,还带来很多其他的改变,具体整理JEP如下(前辍说明:U:修改,A:新增,D:废弃,M:模块化,S:安全):
U 102: Process API UpdatesA 110: HTTP 2 ClientU 143: Improve Contended LockingU 158: Unified JVM LoggingU 165: Compiler ControlU 193: Variable HandlesU 197: Segmented Code CacheU 199: Smart Java Compilation, Phase TwoAM 200: The Modular JDKAM 201: Modular Source CodeA 211: Elide Deprecation Warnings on Import StatementsA 212: Resolve Lint and Doclint WarningsU 213: Milling Project CoinD 214: Remove GC Combinations Deprecated in JDK 8A 215: Tiered Attribution for javacU 216: Process Import Statements CorrectlyU 217: Annotations Pipeline 2.0A 219: Datagram Transport Layer Security (DTLS)AM 220: Modular Run-Time ImagesA 221: Simplified Doclet APIA 222: jshell: The Java Shell (Read-Eval-Print Loop)A 223: New Version-String SchemeU 224: HTML5 JavadocA 225: Javadoc SearchA 226: UTF-8 Property FilesA 227: Unicode 7.0A 228: Add More Diagnostic CommandsUS 229: Create PKCS12 Keystores by DefaultD 231: Remove Launch-Time JRE Version SelectionU 232: Improve Secure Application PerformanceA 233: Generate Run-Time Compiler Tests AutomaticallyA 235: Test Class-File Attributes Generated by javacA 236: Parser API for NashornA 237: Linux/AArch64 PortU 238: Multi-Release JAR FilesD 240: Remove the JVM TI hprof AgentD 241: Remove the jhat ToolA 243: Java-Level JVM Compiler InterfaceUS 244: TLS Application-Layer Protocol Negotiation ExtensionU 245: Validate JVM Command-Line Flag ArgumentsUS 246: Leverage CPU Instructions for GHASH and RSAU 247: Compile for Older Platform VersionsU 248: Make G1 the Default Garbage CollectorAS 249: OCSP Stapling for TLSU 250: Store Interned Strings in CDS ArchivesA 251: Multi-Resolution ImagesU 252: Use CLDR Locale Data by DefaultA 253: Prepare JavaFX UI Controls & CSS APIs for ModularizationU 254: Compact StringsU 255: Merge Selected Xerces 2.11.0 Updates into JAXPU 256: BeanInfo AnnotationsU 257: Update JavaFX/Media to Newer Version of GStreamerU 258: HarfBuzz Font-Layout EngineA 259: Stack-Walking APIUM 260: Encapsulate Most Internal APIsAM 261: Module SystemU 262: TIFF Image I/OA 263: HiDPI Graphics on Windows and LinuxA 264: Platform Logging API and ServiceU 265: Marlin Graphics RendererU 266: More Concurrency UpdatesA 267: Unicode 8.0A 268: XML CatalogsA 269: Convenience Factory Methods for CollectionsU 270: Reserved Stack Areas for Critical SectionsU 271: Unified GC LoggingA 272: Platform-Specific Desktop FeaturesA 273: DRBG-Based SecureRandom ImplementationsU 274: Enhanced Method HandlesAM 275: Modular Java Application PackagingAM 276: Dynamic Linking of Language-Defined Object ModelsU 277: Enhanced DeprecationA 278: Additional Tests for Humongous Objects in G1U 279: Improve Test-Failure TroubleshootingU 280: Indify String ConcatenationA 281: HotSpot C++ Unit-Test FrameworkAM 282: jlink: The Java LinkerA 283: Enable GTK 3 on LinuxU 284: New HotSpot Build SystemA 285: Spin-Wait HintsAS 287: SHA-3 Hash AlgorithmsDS 288: Disable SHA-1 CertificatesD 289: Deprecate the Applet APIAS 290: Filter Incoming Serialization DataD 291: Deprecate the Concurrent Mark Sweep (CMS) Garbage CollectorA 292: Implement Selected ECMAScript 6 Features in NashornA 294: Linux/s390x PortA 295: Ahead-of-Time CompilationU 297: Unified arm32/arm64 PortD 298: Remove Demos and SamplesU 299: Reorganize Documentation
6、Java9带来哪些变化?
通过5中的JEP也可以看出,不过官方给了一个分类:
7、关于模块化
因为Java9对于平台来说最大的变化是模块,涉及到了语法规范和虚拟机的改变,具体有哪些变化呢?其实规范里这些都特意标出来了,按照常规的思考应该类加载会变,还要就是要么像OSGI那样用MANIFEST.MF,要么就新增加一些关键字。实际是增加了一个module-info.java文件,这个有点像已经有的package-info.java,不过package-info.java其实只起到注释包的作用,并没有什么新的关键字,所以没有语法不兼容的情况,但module-info.java则不同了,个人感觉和OSGI里的MANIFEST.MF里的一些用法并没有什么不同,但这样会导致IDE识别不了这些关键字,编译器就需要有对应的修改才能正常兼容。
其实模块化这个想法早在十几年前就已经提出来了,而且也有对应的JSR,因为在构建大型的Java应用时会因为使用的Jar有多个版本,根据路径加载的方式会出现不可控的情况,也就是我们常见的类冲突,因为不同的环境可能会导致不同的类加载顺序,而Java对于相同包名类名的类加载只有第一次生效,后面的不会再加载,所以对于大型系统的复杂依赖这个问题比较严重。还有就是生成的应用越来越大,在嵌入式应用中不太适合。而OSGI最开始也不是模块化的代名词,其实OSGI最开始创立的目的应该是像JCP一样,制定一些网关设备相关规范的,那时Java在嵌入式领域也有了广泛的应用,当时看到了Java的不足,提出来JSR291,这才诞生了OSGI框架,经过十多年的发展,已经相当成熟。
不过JSR376也说明了自己与JSR291的区别,JSR291是在平台之上的,不是平台具备的能力,JSR376的目的是让平台具有模块化的能力,同时平台的模块化能力也能够直接给OSGI框架使用,毕竟OSGI的核心是动态加载的框架。
8、其他关于模块化的应用
OSGI:为什么OSGI可以直接基于现有的JDK达到模块化?其实这个依赖于Java的类加载机制,不同的ClassLoader是可以让同一个类有多个版本加载的,但同一个ClassLoader不能对同一个类的多个版本进行加载。
Pandora:其实这个我觉得应该算是模块化的产物,如果十多年前模块化被纳入JDK,也不会有Pandora了吧。实现的原理也是基于类的加载和对应的ClassLoader有关。
Maven:也算是模块化的应用吧,不过是以pom.xml的方式来管理依赖的,对于冲突也是在pom.xml的依赖管理里来排,但对于像OSGI和Pandora那样的类加载方式却不涉及,完全靠人肉排除多版本依赖的问题,并不能对多差异版本共存的问题有实质性帮助。不过我想Maven的目的并不是解决这个问题的,不擅长也可以理解,Maven主要还是管理依赖和jar包分发,从更上层来避免此类类冲突问题。
转载地址:http://pzmfm.baihongyu.com/