生产环境 JDK6 升级 JDK8
由于 Oracle 已經(jīng)不對 JDK6 和 JDK7 進(jìn)行支持,同時(shí)為了利用 G1 收集器。所以我們在生產(chǎn)環(huán)境中,將項(xiàng)目從 JDK6 升級至 JDK8,并將垃圾收集器由 CMS 換成了 G1。下面對這次升級作一個(gè)總結(jié),并且給出一些大家可能需要用到的資源。
升級指引
升級前首先需要了解一下 Oracle 對 JDK 各個(gè)版本的支持時(shí)間,JDK6, JDK7 分別于 2013, 2015 年停止了公開更新(public update),而 JDK8 將于 2017 年,或者更晚的時(shí)間,停止公開更新,詳細(xì)內(nèi)容可以參考?Oracle Java SE Support Roadmap。
Java 版本之間是有二進(jìn)制向后兼容性的,即 JDK8 的虛擬機(jī)可以運(yùn)行由 JDK7, JDK6 編譯的 class 文件。如果有例外的話,Oracle 會在升級中明確說明。但是如果用 JDK8 了,還將代碼編譯成之前版本的類文件,就意味著無法使用 JDK8 中的新語法特性。Oracle 在大版本之間的升級,都會提供兼容性指南,例如?Compatibility Guide for JDK 8,Java SE 7 and JDK 7 Compatibility。兼容性指南包含的主要內(nèi)容包括:
- 二進(jìn)制兼容性
- 源代碼兼容性
- 行為兼容性
- 類文件變化
- Java SE 與上一版本相比不兼容的地方
- JDK 與上一版本相比不兼容的地方
- Java SE 中移除的特性
- JDK 中移除的特性
- 不建議使用的 API
二進(jìn)制兼容性
JDK7 編譯的代碼可以在 JDK8 下運(yùn)行,JDK8 下編譯的代碼不可以在之前版本的 JDK 中運(yùn)行 。
源代碼兼容性
使用了 JDK8 語法新特性的源代碼,不能在之前版本的 Java 平臺上編譯。不建議使用的 API 在用新?javac?編譯時(shí),會給出警告,除非通過?-nowarn?關(guān)閉。sum.*?下的?API?有所變化,所以,一定要記得不要使用這個(gè)包下的?API,不然升級會很痛苦。
行為兼容性
行為兼容性意味著同樣的輸入,有著同樣的行為。Java 平臺中會有一些故意未指定的行為,在不同的 JDK 版本中,可能會有變化,所以代碼不應(yīng)該依賴于這些行為。如果 JDK 版本變了,行為也變了,可能說明代碼里有 bug。
類文件
JDK8 編譯的類文件,版本號為?52.0。
JDK 及 Java SE 與上一版本的不兼容性
這一部分內(nèi)容比較多,如果從 JDK7 升級至 JDK8,可以參考?Compatibility Guide for JDK 8;如果從 JDK6 升級至 JDK8,需要同時(shí)參考?Compatibility Guide for JDK 8?和?Java SE 7 and JDK 7 Compatibility。
這一部分內(nèi)容里包含了源代碼不兼容性,例如原來在 JDK7 下可以編譯的代碼,在 JDK8 下就不能編譯了。這類錯誤還是比較好查的,編譯一下就可以找出這類錯誤。
或者是一些 GC 選項(xiàng)會被忽略,例如?PermSize。
或者是類文件中添加了一些新內(nèi)容,例如 StackMapTable ,在運(yùn)行時(shí)會對類文件的這個(gè)字段進(jìn)行驗(yàn)證,一些可能會調(diào)整字節(jié)碼的工具,需要更新這個(gè)字段。例如代碼覆蓋率統(tǒng)計(jì)工具,這些工具如果調(diào)整了字節(jié)碼,又沒有對 StackMapTable 進(jìn)行更新。那么高版本的 JDK 就無法運(yùn)行經(jīng)過調(diào)整的字節(jié)碼,在字節(jié)碼校驗(yàn)階段就會失敗。
或者是同一份代碼,由于 JDK8 引入的特性,生成不同字節(jié)碼,最終導(dǎo)致 JDK8 下無法正常運(yùn)行。這類錯誤通常只會在運(yùn)行時(shí)才體現(xiàn)出來,比較難以察覺。例如我在這篇?JDK8 中的類型推斷與重載解析?中描述的這類情況。對這類情況,我們應(yīng)該做到:
- 平時(shí)多寫測試用例
- 用 tcpcopy 引線上流量打壓
這樣,可以讓運(yùn)行時(shí)錯誤或者行為不兼容性更早地暴露出來
GC
從 JDK6 向上升級,在 GC 方面比較重要的就是 G1 這個(gè)垃圾收集器。G1 垃圾收集器在 JDK6u14 中作為實(shí)驗(yàn)特性發(fā)布,在 JDK7 中正式發(fā)布。未來,在 JDK9 中,G1 將會作為默認(rèn)的垃圾收集器,可見 G1 已經(jīng)達(dá)到了比較成熟的階段。所以在 JDK8 中完全可以使用 G1。
而 G1 中比較重要的特性包括:
- 同時(shí)實(shí)現(xiàn)了新生代和老年代兩種 GC 算法
- 各代之間不再有物理隔離,虛擬機(jī)管理的內(nèi)存分為多個(gè) region
- 通過設(shè)置 GC 停頓的期望時(shí)間來調(diào)優(yōu)(-XX:MaxGCPauseMillis)
使用建議包括:
- 適用于管理大內(nèi)存的場景
- 適用于對延遲要求高于吞吐的場景
- 總是將詳細(xì)的 GC 日志記錄在 log 中
- 總是打開?-XX:+ParallelRefProcEnabled?選項(xiàng),實(shí)際環(huán)境中發(fā)現(xiàn)處理引用的過程確實(shí)也比較耗時(shí)
- 避免 Humongous 區(qū)域,即單個(gè)對象大小大于 region 區(qū)大小的 50%
- 盡力避免 Full GC
注意事項(xiàng)包括:
- 不要再設(shè)置新生代大小了,通過調(diào)整停頓時(shí)間,G1 會自動調(diào)整新生代大小
- 停頓時(shí)間只是期望時(shí)間,并不保證 STW 一定在這個(gè)時(shí)間內(nèi)完成。根據(jù)經(jīng)驗(yàn),如果將停頓時(shí)間設(shè)置為 x, 那么 50% 的 GC 會在 x ms 內(nèi)完成
在此次升級過程中,我看過的最重要的資料是一份 presentation:?G1 Garbage Collector Details and Tuning。其中對 G1 中的重要特性,原理,使用建議,參考資料進(jìn)行了說明,強(qiáng)烈建議閱讀。
除此之外,還有幾個(gè)和 G1 相關(guān)的博客可以參考:
- G1GC Concept and Performance Tuning
- Poonam's Weblog
第三方庫
升級 JDK8 的過程中,一些第三方庫也需要同步更新。比較重要的一個(gè)原因在于,一些庫是依賴類文件格式的,如果把代碼編譯到 JDK8 的版本,那么這些庫也需要同步更新。例如:
- 代碼覆蓋率工具:Emma 不支持 JDK8,可以選用 Jacoco
- Spring: 4.x 版本才全面支持 JDK8,之前的版本可能無法正確讀取類文件??梢詤⒖?How Spring achieves compatibility with Java 6, 7 and 8。
同時(shí),也需要注意,第三方庫的升級,也會帶來另外一些問題。例如,我們在升級 Spring 的過程中,就遇到了死鎖問題。
參考資料
- Upgrading major Java versions
- Compatibility Guide for JDK 8
- Java SE 7 and JDK 7 Compatibility
- G1 Garbage Collector Details and Tuning
- Spring Framework 4.0 M1 & 3.2.3 available
總結(jié)
以上是生活随笔為你收集整理的生产环境 JDK6 升级 JDK8的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Vim开发RubyOnRails 环境打
- 下一篇: 控制 计算机某个程序自动开关,电脑自动开
