編譯自https://blog.joda.org/2018/10/adopt-java-12-or-stick-on-11.html
原文作者Stephen Colebourne是一名 Java 開發(fā)者,同時(shí)也是一位知名的 Java 博主和會(huì)議演講者。
如需轉(zhuǎn)載請(qǐng)注明上述來(lái)源信息,其他來(lái)源無(wú)效并視為侵權(quán)
距離 Java 11 的正式發(fā)布已過(guò)去一個(gè)多月,而 Java 12 也正在趕來(lái)的路上。根據(jù)此前開源中國(guó)發(fā)起的一項(xiàng)關(guān)于開發(fā)者使用的 Java 版本的調(diào)查,Java 8 仍然是開發(fā)者的主流選擇,而 Java 11 是 Java 8 之后的首個(gè) LTS 版本,所以有不少開發(fā)者表示會(huì)選擇升級(jí)至 Java 11。按照 Java 的發(fā)布計(jì)劃,Java 12 將于明年 3 月推出。那么問(wèn)題來(lái)了,我們是應(yīng)該采用?Java 12,還是堅(jiān)持使用 Java 11 呢?
可能你會(huì)覺(jué)得這是一個(gè)無(wú)關(guān)緊要的問(wèn)題,但對(duì)于那些需要在 JVM 中使用 Java 的開發(fā)者,或是比較看重 Java 新特性的開發(fā)者,這是一項(xiàng)十分重要的決策。這篇文章將和大家就這個(gè)問(wèn)題進(jìn)行相關(guān)的分析。
Java 發(fā)布計(jì)劃
現(xiàn)在每六個(gè)月就會(huì)發(fā)布一個(gè)新的 Java 版本,所以盡管 Java 11 才發(fā)布不久,但距離 Java 12 的發(fā)布也就剩下不到五個(gè)月的時(shí)間。作為發(fā)布計(jì)劃的一部分,某些版本會(huì)被指定為長(zhǎng)期支持版本(LTS),它們會(huì)獲得四年或更長(zhǎng)時(shí)間的技術(shù)支持和安全補(bǔ)丁更新。所以這些版本通常會(huì)被稱為“主要版本” —— 不是因?yàn)樗鼈儞碛懈嗟墓δ芴匦?,而是因?yàn)樗鼈兙哂虚L(zhǎng)期的技術(shù)支持。
預(yù)計(jì) Java 11 的更新補(bǔ)丁(11.0.1, 11.0.2, 11.0.3 等)將比 Java 8 的補(bǔ)丁(8u20, 8u40, 8u60)更小更簡(jiǎn)單。因?yàn)?Java 11 的更新將更加集中在安全補(bǔ)丁上,不會(huì)像 Java 8 的更新那樣帶來(lái)內(nèi)部的功能增強(qiáng)。Oracle 希望將?Java 12, 13, 14 等這些版本當(dāng)做是小更新版本,類比成 Java 8 的話,即是 Java 11u20, 11u40。
Oracle 高級(jí)員工一再認(rèn)為像 8u20 和 8u40 這樣的更新常常會(huì)帶來(lái)破壞性的變更,但本文作者表示這不是自己的經(jīng)歷,他記得的唯一有破壞性的變化是為?Javadoc?添加了--allow-script-in-comments,但它也不是 Java 的核心部分。因此,他從不擔(dān)心升級(jí)到最新版本帶來(lái)的影響 —— 因?yàn)檫@是 Java 平臺(tái)的核心優(yōu)勢(shì)。
下面深入了解一下為什么在舊的發(fā)布模式下,升級(jí)版本不會(huì)導(dǎo)致任何問(wèn)題。先看一下新舊發(fā)布模式之間的差異:
模式舊的發(fā)布模式新的發(fā)布模式
升級(jí)系列Java 主要版本Java 更新版本Java 版本系列Java 補(bǔ)丁版本
頻率每隔3年左右每6個(gè)月一次每6個(gè)月一次每3個(gè)月一次

Oracle 的官方觀點(diǎn)認(rèn)為:與 Java 7->8->9 相比,Java 9->10->11 的升級(jí)和?8->8u20->8u40 更相似。
表格清楚地顯示新模式下的 Java 版本發(fā)布都會(huì)包含許多變更,包括語(yǔ)言變更和 JVM 變更,這兩者都會(huì)對(duì) IDE、字節(jié)碼庫(kù)和框架產(chǎn)生重大影響。此外,不僅會(huì)新增其他 API,還會(huì)有 API 被刪除(這在 Java 8 之前沒(méi)有發(fā)生過(guò))。
Oracle 的觀點(diǎn)是,因?yàn)槊總€(gè)版本僅在前一個(gè)版本發(fā)布后的6個(gè)月推出,所以不會(huì)有太多新的“東西”,因此升級(jí)并不困難。雖然如此,但這不是重點(diǎn)。重要的是升級(jí)是否有可能會(huì)破壞代碼。很明顯,從 11 -> 12 -> 13?開始,代碼遭受破壞的可能性要大于?8 -> 8u20 -> 8u40。
11 -> 12 -> 13 與 8u20 -> 8u40 等這樣的更新主要區(qū)別在于對(duì)字節(jié)碼版本的更改以及對(duì)規(guī)范的更改,對(duì)字節(jié)碼版本的更改往往特別具有破壞性,大多數(shù)框架都大量使用與每個(gè)字節(jié)碼版本密切相關(guān)的 ASM 或 ByteBuddy 等庫(kù)。而?8u20 -> 8u40 仍然使用相同的 Java SE 規(guī)范,具有所有相同的類和方法,不同于從 Java 12 移動(dòng)到 13。
除此之外,Oracle 的另一個(gè)聲明也十分值得我們關(guān)注。聲明透露出的消息是,如果堅(jiān)持使用 Java 11 并計(jì)劃在下一個(gè) LTS 版本(即 Java 17)發(fā)布時(shí)再進(jìn)行升級(jí),開發(fā)者可能會(huì)發(fā)現(xiàn)自己的項(xiàng)目代碼無(wú)法通過(guò)編譯。所以請(qǐng)記住,Java 新的開發(fā)規(guī)則現(xiàn)在聲明可以在一個(gè)版本中棄用某個(gè) API 方法,并在下一個(gè)版本中刪除它。
采用新版本 Java 的注意事項(xiàng)
在本節(jié)中,將概述在采用新版本 Java 之前必須考慮的一些注意事項(xiàng)/風(fēng)險(xiǎn)。
被新版本系列“綁定”
如果采用了 Java 12 并使用新的語(yǔ)言特性或新的 API,這意味著實(shí)際上你已將項(xiàng)目綁定到 Java 的新版本系列。接下來(lái)你必須采用 Java 13, 14, 15, 16 和 17,并且必須在下一個(gè)版本發(fā)布后的一個(gè)月內(nèi)采用每個(gè)新版本。
使用了新版本,每個(gè)版本的使用壽命為六個(gè)月,并且在發(fā)布后僅七個(gè)月就過(guò)時(shí)了。這是因?yàn)槊總€(gè)版本只有在六個(gè)月內(nèi)提供安全補(bǔ)丁,發(fā)布后1個(gè)月的第一個(gè)補(bǔ)丁和發(fā)布后4個(gè)月的第二個(gè)補(bǔ)丁。7個(gè)月后,下一組安全補(bǔ)丁會(huì)發(fā)布,但舊版本不能獲取更新。
因此,你要判斷自身的開發(fā)流程是否允許升級(jí) Java 版本,時(shí)間窗口方面會(huì)不會(huì)太狹窄?
升級(jí)的“絆腳石”
實(shí)際使用中有很多阻止我們升級(jí) Java 的因素,下面列出一些常見(jiàn)的:
開發(fā)資源不足:你的團(tuán)隊(duì)可能會(huì)非常忙碌或規(guī)模太小,你能保證兩年后從 Java 15 升級(jí)到 16 的開發(fā)時(shí)間嗎?
構(gòu)建工具和 IDE:你使用的 IDE 是否會(huì)在發(fā)布當(dāng)天支持每個(gè)新版本?Maven? Gradle 呢??如果不是,你有后備計(jì)劃嗎?請(qǐng)記住,你只有1個(gè)月的時(shí)間來(lái)完成升級(jí)、測(cè)試并將其發(fā)布到生產(chǎn)環(huán)境中。此外還包括 Checkstyle,JaCoCo,PMD,SpotBugs 等等其他工具。
依賴關(guān)系:你的依賴關(guān)系是否都準(zhǔn)備好用于每個(gè)新版本?請(qǐng)記住,它不僅僅是直接依賴項(xiàng),而是技術(shù)堆棧中的所有內(nèi)容。字節(jié)碼操作庫(kù)尤其受到影響,例如 ByteBuddy 和 ASM。
框架:這是另一種依賴,但是一個(gè)大而重要的依賴。在一個(gè)月的狹窄時(shí)間窗口內(nèi),Spring 會(huì)每六個(gè)月發(fā)布一個(gè)新版本嗎??Jakarta EE(以前的 Java EE)會(huì)嗎?如果它們不這樣做會(huì)怎么樣?
云 / 托管 / 部署
你是否可以控制代碼在生產(chǎn)環(huán)境中的運(yùn)行位置和方式?例如,如果你在 AWS Lambda 中運(yùn)行代碼,則無(wú)法控制。AWS Lambda 沒(méi)有采用 Java 9或10,甚至沒(méi)有采用 Java 11。所以除非 AWS 提供公共保證以支持每個(gè)新的 Java 版本,否則根本無(wú)法采用 Java 12。
如何托管你的 CI 系統(tǒng)?Jenkins, Travis, Circle, Shippable, GitLab 會(huì)快速更新嗎?如果不是,你會(huì)怎么做?
對(duì)未來(lái)的預(yù)測(cè)
如果已經(jīng)閱讀了上面的列表,并且你的代碼和流程可以應(yīng)對(duì)。這十分好,但更重要的是要明白,你也在限制未來(lái)進(jìn)行改變的能力。例如,你的代碼可能今天不在 AWS Lambda 上運(yùn)行,但未來(lái)三年呢?
為采用新版本進(jìn)行規(guī)劃
如果正在考慮采用新版本的 Java,建議你準(zhǔn)備一份現(xiàn)在所依賴的所有內(nèi)容的清單,或者可能在未來(lái)3年內(nèi)會(huì)依賴的。你需要保證該列表中的所有內(nèi)容都能正常工作,并與新版本一起升級(jí),或者如果該依賴項(xiàng)不再更新,請(qǐng)制定好計(jì)劃。作者提供了他的清單:
Amazon AWS
Eclipse
IntelliJ
Travis CI
Shippable CI
Maven
Maven plugins (compile, jar, source, javadoc, etc)
Checkstyle, 以及相關(guān)的 IDE 插件和 maven 插件
JaCoCo, 以及相關(guān)的 IDE 插件和?maven 插件
PMD 和相關(guān)的 maven 插件
SpotBugs 和相關(guān)的 maven 插件
OSGi bundle metadata tool
Bytecode 工具(Byte buddy / ASM etc)
超過(guò) 100 個(gè) jar 包依賴項(xiàng)
說(shuō)了這么多,作者當(dāng)然不是鼓勵(lì)大家不進(jìn)行升級(jí),新語(yǔ)言特性帶來(lái)的好處以及性能增強(qiáng)會(huì)讓開發(fā)者受益,但升級(jí)背后的風(fēng)險(xiǎn)也應(yīng)該考慮進(jìn)去。
其他第三方產(chǎn)商的聲明
Spring 框架已經(jīng)在視頻中表達(dá)了對(duì) Java 12 的策略。關(guān)鍵部分是:
“Java 8 和 11 作為 LTS 版本會(huì)持續(xù)獲得我們的正式支持,對(duì)于過(guò)渡版本,我們也會(huì)盡最大努力支持。如果你升級(jí)到 Java 11,我們非常愿意和你合作,但它們不會(huì)獲得正式的生產(chǎn)環(huán)境支持。因?yàn)殚L(zhǎng)期支持版本才是我們關(guān)注的重心,對(duì)于 Java 12 及更高版本我們會(huì)盡最大的努力?!?/p>
作為典型軟件供應(yīng)商的一個(gè)例子,Liferay 聲明如下:
Liferay 已決定不會(huì)對(duì) JDK 的每個(gè)主要版本進(jìn)行認(rèn)證。我們將選擇遵循 Oracle 的主導(dǎo)并僅認(rèn)證標(biāo)記為 LTS 的版本。——?Liferay博客
總結(jié)
相信肯定已經(jīng)有開發(fā)團(tuán)隊(duì)采用了新版本的 Java,但希望他們是經(jīng)過(guò)思考判斷之后做出的決定。除了文章中提到的問(wèn)題,還會(huì)有很多其他在升級(jí)前需要思考的因素,歡迎在評(píng)論中留下你的看法。