从Java 8升级到Java 11应该注意的问题

从Java 8迁移到Java 11比大多数升级更棘手。以下是这个过程的一些注意事项。

模块
在Java 9中Java引入了历史上最大的变化之一 是模块,但:

不必将你自己的代码模块化以后才能升级到Java 11。

在大多数情况下,放在类路径classpath上的代码能继续在Java 9及更高版本上有效被发现和运行,但是如果将模块放置类路径上会被忽略,这对于库包发布者来说非常糟糕,但对于应用程序开发者是个好事情。

因此,在升级到Java 11时尽可能地先不用模块化,而将自己的应用程序转换为Java模块应该等待时机,等待大规模开源的依赖库包真正采用模块化后的几年内才开始实施模块化,现在,尝试模块化很痛苦,因为你的依赖包很少是模块化的。

(如果将程序模块化的主要原因是由于使用jlink能缩小JDK的大小,也完全不需要模块化来实现这个目标 - 只需使用Maven创建一个jar- with-dependencies,其中module-info不配置require,不配置export( no-requires和no-exports )。

删除了JDK的部分内容
JDK的有关Java EE和Corba的一部分被删除,它们不再适合JDK,或者可以在其他地方维护。

如果您使用Corba,那么几乎没有人可以帮助你,但是,如果你使用Java EE模块,那么在大多数情况下,对已删除代码的修复应该很简单。只需添加适当的Maven即可。

在Java客户端方面,已经删除了Java WebStart ,替代方案会更加棘手,请考虑使用Getdown或Update4J。

不安全和朋友
多年来, Sun和Oracle一直在告诉开发人员不要使用sun.misc.Unsafe和其他尖端的JDK API。很长一段时间,Java 9将要删除这些,但这实际上从未发生过。

但是在Java 11,首次访问受限API时,你可能会收到警告,此警告仅打印一次。这是一个有用的提醒,你的代码或依赖正在做一些“顽皮”的事情,需要在某个时候修复。

您还会发现Java 11有许多专门设计的新API,以避免使用Unsafe人需要,如果你使用的是“非法”API,请优先调查这些新API,例如, Base64, MethodHandles.privateLookupIn, MethodHandles.Lookup.defineClass, StackWalker 和Variable Handles。

工具和图书馆
模块化和新的六个月发布周期这两个机制共同对工具和库开发人员使用产生了真正的影响,一些项目已经能够跟上,有些人在努力,有些人失败了。

升级到Java 11时,关键任务是将所有依赖项更新为最新版本,如果自Java 9问世以来这些依赖项还没有发布新版本,那么这些依赖可能需要额外的关注或测试,确保您也更新了IDE。

但是,不仅需要更新应用程序的依赖项,Maven也是如此,大多数Maven插件已将主要版本更改为v3.x,将Maven本身升级到v3.5.4也是有益的。

可悲的是,核心maven团队规模很小,因此仍有一些问题需要解决,但是,如果你的Maven构建非常合理且简单,那么通常应该没问题。但请注意,将插件从v2.x升级到v3.x可能需要更改配置,而不仅仅是与模块相关联。例如,Maven Javadoc插件已重命名该argLine属性。

需要注意的一个关键点是Maven使用模块进行操作的方式,当Maven编译器或surefire插件找到一个模块化的jar文件(即带有module-info.class)时,它可以将该jar放在模块路径而不是类路径上,因此,即使你可能打算只在类路径上运行你的应用程序,Maven可能部分地在类路径上编译和测试代码,而另外一部分会在模块路径上编译代码,在目前,没有什么可以搞定这个问题。

有时你的构建需要更大的更改。例如,需要将Findbugs更改为SpotBugs,并将Cobertura改为JaCoCo。

这些构建更改可能需要一些时间 。

总结
当我完成迁移之后,我的结论是痛苦主要在于维护与Java 8的兼容性,将应用程序全部只到Java 11应该更简单,因为不需要与Java 8保持联系。