探秘Java9

简介:

2017年9月Java9正式发布,之前就一直听说新版会有模块化,仔细了解下Java9的发展史,这个模块化确实比较坎坷,当然,好事多磨嘛。

1、相关组织

JUG:Java User Groups(Java用户群),以下是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、JSR376:JPMS

Java9的规范是JSR379,但379又依赖JSR376,也就是Java的平台模块化,在JDK9的源码里也可以看到“@spec JPMS”,这个表示的是这块代码是JSR376里要求实现或修改的。

5、JSR 379: JavaTM SE 9 Release Contents涉及哪些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 Updates
A  110: HTTP 2 Client
U  143: Improve Contended Locking
U  158: Unified JVM Logging
U  165: Compiler Control
U  193: Variable Handles
U  197: Segmented Code Cache
U  199: Smart Java Compilation, Phase Two
AM 200: The Modular JDK
AM 201: Modular Source Code
A  211: Elide Deprecation Warnings on Import Statements
A  212: Resolve Lint and Doclint Warnings
U  213: Milling Project Coin
D  214: Remove GC Combinations Deprecated in JDK 8
A  215: Tiered Attribution for javac
U  216: Process Import Statements Correctly
U  217: Annotations Pipeline 2.0
A  219: Datagram Transport Layer Security (DTLS)
AM 220: Modular Run-Time Images
A  221: Simplified Doclet API
A  222: jshell: The Java Shell (Read-Eval-Print Loop)
A  223: New Version-String Scheme
U  224: HTML5 Javadoc
A  225: Javadoc Search
A  226: UTF-8 Property Files
A  227: Unicode 7.0
A  228: Add More Diagnostic Commands
US 229: Create PKCS12 Keystores by Default
D  231: Remove Launch-Time JRE Version Selection
U  232: Improve Secure Application Performance
A  233: Generate Run-Time Compiler Tests Automatically
A  235: Test Class-File Attributes Generated by javac
A  236: Parser API for Nashorn
A  237: Linux/AArch64 Port
U  238: Multi-Release JAR Files
D  240: Remove the JVM TI hprof Agent
D  241: Remove the jhat Tool
A  243: Java-Level JVM Compiler Interface
US 244: TLS Application-Layer Protocol Negotiation Extension
U  245: Validate JVM Command-Line Flag Arguments
US 246: Leverage CPU Instructions for GHASH and RSA
U  247: Compile for Older Platform Versions
U  248: Make G1 the Default Garbage Collector
AS 249: OCSP Stapling for TLS
U  250: Store Interned Strings in CDS Archives
A  251: Multi-Resolution Images
U  252: Use CLDR Locale Data by Default
A  253: Prepare JavaFX UI Controls & CSS APIs for Modularization
U  254: Compact Strings
U  255: Merge Selected Xerces 2.11.0 Updates into JAXP
U  256: BeanInfo Annotations
U  257: Update JavaFX/Media to Newer Version of GStreamer
U  258: HarfBuzz Font-Layout Engine
A  259: Stack-Walking API
UM 260: Encapsulate Most Internal APIs
AM 261: Module System
U  262: TIFF Image I/O
A  263: HiDPI Graphics on Windows and Linux
A  264: Platform Logging API and Service
U  265: Marlin Graphics Renderer
U  266: More Concurrency Updates
A  267: Unicode 8.0
A  268: XML Catalogs
A  269: Convenience Factory Methods for Collections
U  270: Reserved Stack Areas for Critical Sections
U  271: Unified GC Logging
A  272: Platform-Specific Desktop Features
A  273: DRBG-Based SecureRandom Implementations
U  274: Enhanced Method Handles
AM 275: Modular Java Application Packaging
AM 276: Dynamic Linking of Language-Defined Object Models
U  277: Enhanced Deprecation
A  278: Additional Tests for Humongous Objects in G1
U  279: Improve Test-Failure Troubleshooting
U  280: Indify String Concatenation
A  281: HotSpot C++ Unit-Test Framework
AM 282: jlink: The Java Linker
A  283: Enable GTK 3 on Linux
U  284: New HotSpot Build System
A  285: Spin-Wait Hints
AS 287: SHA-3 Hash Algorithms
DS 288: Disable SHA-1 Certificates
D  289: Deprecate the Applet API
AS 290: Filter Incoming Serialization Data
D  291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector
A  292: Implement Selected ECMAScript 6 Features in Nashorn
A  294: Linux/s390x Port
A  295: Ahead-of-Time Compilation
U  297: Unified arm32/arm64 Port
D  298: Remove Demos and Samples
U  299: Reorganize Documentation

6、Java9带来哪些变化?

通过5中的JEP也可以看出有9带来了哪些变化,不过官方还是给了一个分类如下:

主要分为:平台、语言、核心库、网络、安全、客户端库、拓展标记语言 这7类。

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包分发,从更上层来避免此类冲突问题。

目录
相关文章
|
2月前
|
存储 缓存 安全
Java基础扫盲(二)
Java基础扫盲(二)
|
安全 算法 Java
Java 17 VS Java 8: 新旧对决,这些Java 17新特性你不容错过
Java 17 VS Java 8: 新旧对决,这些Java 17新特性你不容错过
2555 0
|
开发框架 分布式计算 安全
Java小史:Java简介和现状
简单介绍下Java的前世今生和现状
250 0
Java小史:Java简介和现状
|
安全 Java 数据中心
Java缘起篇
Java 是由 Sun Microsystems 在 1995 年首先发 布的编程语言和计算平台。有许多应用程序和 Web 站 点只有在安装 Java 后才能正常工作,而且这样的应 用程序和 Web 站点日益增多。Java 快速、安全、可 靠。从笔记本电脑到数据中心,从游戏控制台到科学 超级计算机,从手机到互联网,Java 无处不在!
140 0
Java缘起篇
|
Oracle 安全 前端开发
java面试:谈谈你对java平台的理解?
java面试:谈谈你对java平台的理解?
java面试:谈谈你对java平台的理解?
|
消息中间件 设计模式 Dubbo
三流Java搞技术,二流Java搞框架,一流Java…
三流Java搞技术,二流Java搞框架,一流Java…
293 0
三流Java搞技术,二流Java搞框架,一流Java…
|
Java 数据库连接 Linux
Java必备知识(一)
一、接口与抽象类的区别?
101 0
|
XML 算法 Java
|
Kubernetes 算法 Java
JAVA必备知识: RuntimeClass
Runtime之Class结构 runtime(内存管理) 运行时刻是指一个程序在运行(cc或者在被执行)的状态。也就是说,当你打开一个程序使它在电脑上运行的时候,那个程序就是处于运行时刻。在一些编程语言中,把某些可以重用的程序或者实例打包或者重建成为“运行库"。这些实例可以在它们运行的时候被链接或者被任何程序调用。 开发者有时候会在什么东西应该在编译的时候加载进来以及什么东西该在运行的时候使用之间做出抉择,前者有时候被称为编译时期。 一段时间以来,技术类作者都拒绝使用"运行时刻"作为一种术语,他们坚持类似于"一个程序在运行"之类的说法,用以避免需要一个专门的术语。后来,这个术语逐渐地蔓延到通
461 0
JAVA必备知识: RuntimeClass