如果你依赖于本节中谈论的一个或多个特性,那么必须采纳一些方法,担保项目正常运行。没有人乐意对不会引起明显问题的事情返工,但是看看这些特性(大部分我没有利用过),我只能想象在没有它们的情形下,JDK内部构造会变得多么大略。
1 不再支持紧凑配置正如我前几篇所述,模块系统的一个目标是,利用户能够创建仅包含所需模块的运行时镜像。对付存储有限的小型设备和虚拟化环境来说,这一点非常主要,由于两者都非常关心运行时镜像的大小。当确定模块系统不会随Java 8发布时(曾经操持在Java 8中发布模块系统),紧凑配置作为临时办理方案出身了。
Java SE 8 API和JRE的3个紧凑配置仅包含支持这些API子集所需的类。在选取与运用程序需求相匹配的配置后,利用javac选项-profile进行编译(以确保所选子集精确),然后运行相应的字节码。

在模块系统中,由于可以利用jlink创建更灵巧的运行时镜像,不再须要紧凑配置,因此Java 9及以上版本仅在编译Java 8时接管-profile选项。要根据选择的模块进行编译,可以利用我前几篇文章所述的--limit-modules选项。
以下是获取与3个紧凑配置相同的API所需的模块。
1)compact1配置——java.base、java.logging和java.scripting。
2) compact2配置——compact1中的模块加上java.rmi、java.sql和java.xml。
3) compact3配置——compact2中的模块加上java.compiler、
java.instrument、java.management、java.naming、java.prefs、java.security.jgss、java.security.sasl、java.sql.rowset和java.xml.crypto。
相较于依赖固定的选择,本书推举不同的方法。利用jlink创建仅包含所需平台模块的镜像。如果运用程序及其依赖是完备模块化的,乃至可以包括运用程序模块。
2 扩展机制被移除Java 9之前的扩展机制使人们可以向JDK中添加类,而无须将它们放在类路径上。扩展机制可以从各种目录加载类:系统属性java.ext.dirs指定的目录、JRE中的lib/ext目录,或特定于平台的系统目录。Java 9移除了此功能,如果JRE目录存在或系统属性已设置,编译时和运行时将退出并提示缺点信息。
替代方案如下:
1) java和javac选项--patch-module将内容注入模块;
2) java和javac选项--upgrade-module-path将可升级的平台模块
更换为另一个平台模块(拜会我上篇文章);
3) 扩展工件可以放置在类路径上。
3 授权标准覆盖机制被移除Java 9之前,授权标准覆盖机制使得人们可以用自定义实现更换某些API。它从系统属性java.endorsed.dirs指定的目录或JRE中的lib/endorsed目录中加载类。
Java 9移除了此功能,如果JRE目录存在或系统属性已设置,编译器和运行时将退出,并提示缺点信息。它的替代方案与扩展机制相同。
4 某些启动类路径选项被移除移除了-Xbootclasspath和-Xbootclasspath/p选项,利用如下替代选项:
1) javac选项--system指定系统模块的可选路径;
2) javac选项--release指定可选平台的版本;
3) java和javac选项--patch-module将内容注入初始模块图中的模块中。
5 不支持Java 5编译Java编译器可以处理来自各种Java版本(例如利用-source指定的Java7)的源代码,并且可以为各种JVM版本(例如利用-target指定Java8)天生字节码。Java过去遵照“1+3”版本策略,意味着javac 9支持Java9以及Java 8、Java 7和Java 6版本。
在javac 8上设置-source 5或-target 5会产生“已废弃”警告,javac9也不再支持这样做。在Java 9上设置-source 6或-target 6会导致相同的警告。现在,由于Java每6个月发布一次,以是此策略已不再适用。Java 10、Java 11和Java 12也可以编译Java 6的代码。
把稳 编译器可以识别和处理以前所有JDK的字节码,只是不再天生Java 6之前的字节码。
6 JRE版本选择被移除在Java 9之前,人们可以利用java的-version:N选项(或相应的清单条款)来启动采取版本为N的JRE的运用程序。
在Java 9中,该功能被移除了:如果在命令行中指定该选项,Java启动器会提示缺点信息,并退出;如果在manifest条款中指定该选项,Java启动器则会打印警告,并且忽略该选项。如果你一贯依赖该功能,下面是Java文档对此提出的建议。
当代运用程序常日通过Java Web Start(JNLP)、操作系统的打包系统或安装程序进行支配。这些技能有自己管理所需JRE的方法,可以根据须要查找、下载或更新对应的JRE。这使得启动器的启动时JRE版本选择被废弃。
文档认为利用-version:N的运用程序不足当代——这个说法太粗鲁了。顺便说一句,如果你的运用程序依赖于该功能,除了放弃它别无选择。可采取的手段包括将其与最得当的JRE捆绑在一起。
二 一着不慎,满盘皆输除模块系统带来的较大寻衅外,还有一些较小的变动(常日与JPMS无关)同样会造成麻烦。
1)版本字符串的新格式。
2)移除多个JDK和JRE工具。
3)单个下划线不再是有效的标识符。
4)更新Java网络启动协议(JNLP)的语法。
5)删除JVM选项。
只管本书不想在这里花费太多韶光,但也不想留下一些妨碍人们进行迁移的陷阱。因此,本书将对每一条进行简要阐明。
1 新的版本字符串在历经20多年之后,Java终于正式停滞采取1.x进行版本命名。从此,系统属性java.version、java.runtime.version、java.vm.version、java.specification.version和java.vm.specification.version不再以1.x开头,而因此x开头。
同样,java -version返回x,以是在Java 9上人们会得到9.something。
版本字符串格式
新版本字符串的确切格式仍在变革中。在Java 9中,人们将得到9.${MINOR}.${SECURITY}.${PATCH},个中${SECURITY}在发布次要版本时不会重置为0——人们始终可以查看该数字,判断哪个版本包含更多安全修补程序。
在Java 10及更高版本中,人们将得到${FEATURE}.${INTERIM}.${UPDATE}.${PATCH},个中${FEATURE}从10开始,并在每6个月发布一次新功能版本时增大。
${INTERIM}的功能与${MINOR}一样,但是由于在新的方案中没有操持引入次要版本,因此假定它始终保持为0。
很遗憾,这有一个副浸染:对版本敏感的代码可能会溘然停滞正常事情,而这会导致奇怪的行为。对所涉及的系统属性进行全文搜索可以找到此类代码。
至于更新这些代码,如果你乐意将项目升级到Java 9及以上版本,就可以避免对系统属性进行解析,转而利用新的Runtime.Version类型,这要随意马虎得多。
2 工具减少
JDK积累了大量的工具,但随着韶光的推移,有些工具变得多余或被其他工具取代,而个中一些包含在Java 9的移革职单中。
1)JDK不再包括JavaDB。后者是一个Apache Derby DB,可以从TheApach DB Project网站下载。
2)VisualVM不再与JDK捆绑在一起,而是成了一个独立的项目。
3)hprof代理库已被删除,替代其功能的工具有jcmd、jmap和JavaFlight Recorder。
4)删除了jhat堆可视化工具。
5)删除了java-rmi.exe和java-rmi.cgi启动程序。替代方法是利用servlet通过HTTP代理RMI。
6)native2ascii工具可以将基于UTF-8的属性资源包转换为ISO-8859-1。但是,Java 9及以上版本支持基于UTF-8的包,因此该工具变得多余并被删除。
此外,所有与JEE干系的命令行工具(比如wsgen和xjc)在Java 11上不再可用,由于它们连同所属模块一起被删除了(JEE模块的详细信息拜会我上篇文章)。
3 噜苏的事情以下是导致Java 9构建失落败的一个缘故原由。从Java 8开始,单个下划线_不再用作标识符,如果在Java 9上这样利用它,就会涌现编译缺点。这样做是为了回收下划线,将其作为可能的关键字。未来的Java版本将授予它分外的意义。
另一个缘故原由是Thread.stop(Throwable)会抛出UnsupportedOperationException非常。只管其他几个stop的重载方法事情正常,但是本书强烈反对利用它们。
JNLP语法已经更新,以符合XML规范并“肃清不一致,使代码掩护更方便,并增强安全性”。
每个Java版本都移除了一些废弃的JVM选项,Java 9也不例外。Java 9对垃圾网络的变动较多,一些组合不再得到支持(DefNew +CMS、ParNew + SerialOld、增量CMS),一些配置被移除(-Xincgc、-XX:+CMSIncrementalMode、-XX:+UseCMSCompactAtFullCollection、-XX:+CMSFullGCsBeforeCompaction、-XX:+UseCMSCollectionPassing),一些配置被废弃(-xx:+UseParNewGC)。
接下来的Java 10移除了-Xoss、-Xsqnopause、-Xoptimize、-Xboundthreads和-Xusealtsigs。
4 Java 9、Java 10和Java 11中新废弃的功能本节列出了Java 9、Java 10和Java 11中废弃的一些内容:
1)java.applet包中的Applet API,以及appletviewer工具和Java浏览器插件;
2)Java Web Start、JNLP和javaws工具;
3)并发标记打消(CMS)垃圾网络器;
4)用-Xprof激活HotSpot FlatProfiler;
5)policytool安全工具。
Java 10和Java 11中删除的废弃功能如下:
1)Java 10删除了FlatProfiler和policytool;
2)Java 11删除了Applet API和Web Start。
更多干系信息、详细信息和建议的替代方案,请查看发布解释和标记为要删除的废弃代码列表。
三 小结1 JEE模块在Java 9中遭到废弃,在Java 11中被删除。须要尽快找到一个第三方依赖来知足需求。
2 在Java 9和Java 10中,默认情形下这些模块不会被解析,这可能导致编译时和运行时缺点。要办理该问题,要么利用实现相同API的第三方依赖,要么让JEE模块与--add-modules一起利用。
3 运用程序类加载器不再属于URLClassLoader类型,因此像(URLClassLoader)getClass().getClassLoader()这样的代码会失落败。办理方案包括:只依赖ClassLoader API,纵然这意味着必须删除某个特性(建议);创建一个层来动态加载新代码(推举);或者侵入类加载器内部,利用BuiltinClassLoader乃至AppClassLoader(不推举)。
4 运行时镜像的目录构造发生了变革,你可能必须更新你的工具(特殊是IDE)才能利用Java 9或更高版本。操作JDK/JRE目录的代码或系统资源的URL也须要更新。
5 对构成平台的类进行修正的一些机制被删除。模块系统为个中的大多数供应了替代方案。
1)不要利用紧凑的概述文件,而是利用jlink创建运行时镜像,并利用--limit-modules配置编译。
2)利用--patch-module、--upgrade-module-path或类路径,而不是扩展机制或授权标准机制。
3)利用--system、--release或--patch-module代替-Xbootclasspath选项。
6 不再支持编译Java 5,也不再支持利用-version:N选项基于特定Java版本启动运用程序。
7 Java的命令行工具和系统属性java.version打印的版本为9.${MINOR}.${SECURITY}.${PATCH}(Java 9),或者${FEATURE}.${INTERIM}.${UPDATE}.${PATCH}(Java 10或更新版本),这意味着Java x版本以x开头而不是1.x。全新的APIRuntime.Version使得对这个属性的解析不再必要。
8 以下工具被删除了。
1)Java 9:JavaDB、VisualVM、hprof、jhat、javarmi.exe、java-rmi.cgi和native2ascii。
2)Java 10:policytool。
3)Java11:idlj、orbd、schemagen、servertool、tnameserv、wsgen和xjc。
9 单一下划线不再是有效的标识符。
10 JNLP语法已经更新,以符合XML规范。以是人们可能不得不更新JNLP文件。
11 每个Java版本都会删除弃用的JVM命令行选项,这可能会使一些脚本不能正常事情。
12 Java 9废弃了Applet技能和Java Web Start,Java 11则删除了它们