Java8升級Java11備忘錄

1、如何選擇JDK與Java版本

  • 關於JDK:目前有哪些JDK?它們相互之間什麼關係與區別?
  • 關於Java版本:目前有哪些Java發行版本?如何選擇?

1.1 關於JDK

目前主要有Oracle JDK,OpenJDK和其餘一些企業編譯的JDK。html

1.1.1 OpenJDK與Oracle JDK

簡單地說,OpenJDK是OracleJDK的開源版本。java

如下OpenJDK的介紹來自維基百科:mysql

OpenJDK原是Sun Microsystems公司爲Java平臺構建的Java開發環境(JDK)的開源版本,徹底自由,開放源碼。Sun Microsystems公司在2006年的JavaOne大會上稱將對Java開放源代碼,於2009年4月15日正式發佈OpenJDK。甲骨文在2010年收購Sun Microsystem以後接管了這個項目。

歷史:
2008年5月,Fedora 9及Ubuntu 8.04於發行版中發佈OpenJDK,完整地基於自由及開放源代碼的OpenJDK。
2008年6月,IcedTea 6(Fedora 9上的一個包版本的OpenJDK)宣佈已經過Technology Compatibility Kit測試,能夠稱得上是一個徹底兼容的Java 6的運行環境。
2008年7月12日,Debian接受了OpenJDK-6的不穩定版本,但當前狀況已經穩定。OpenJDK也能夠在openSUSE、Red Hat Enterprise Linux及其派生系統,如CentOS中找到。
自2008年7月,OpenJDK 7能夠運行在Mac OS X和其餘的BSD發行版。
2009年7月,Ubuntu 9.04中的二進制版本OpenJDK在Java SE 6 JCK中經過了全部的兼容性測試。
2016年8月22日,Google在Android 7.0 Nougat中,將專利的JDK替換成開源方案的OpenJDK,以完全解決Java的專利問題。

Oracle JDK以前被稱爲SUN JDK,甲骨文收購SUN以後更名爲Oracle JDK。實際上,Oracle JDK也是基於OpenJDK源代碼構建的,所以Oracle JDK和OpenJDK之間並無重大的技術差別,基本上能夠認爲性能、功能和執行邏輯上二者是一致的。linux

2020-05-09-16-21-05.png

二者的不一樣之處主要有:spring

  • 受權協議的不一樣:OpenJDK採用GPL V2協議,而Oracle JDK則採用JRL。兩個協議都是開放源代碼的,可是在使用上不一樣。GPL V2容許在商業上使用,JRL只容許我的研究使用。
  • OpenJDK源代碼不完整:在採用GPL協議的OpenJDK中,SUN JDK的一部分源代碼由於產權的問題沒法開放給OpenJDK使用,其中最主要的部份就是JMX中的可選元件SNMP部份的代碼。這些不能開放的源代碼被做成plug,供OpenJDK編譯時使用。固然你也能夠選擇不要使用plug。另外,在OpenJDK6中Icedtea則爲這些不完整的部分開發了相同功能的源代碼,促使OpenJDK更加完整。
  • 部分源代碼用開源代碼替換:因爲產權的問題,不少產權不是SUN的源代碼被替換成一些功能相同的開源代碼,好比說字體柵格化引擎就使用了Free Type代替。
  • OpenJDK只包含最精簡的JDK:OpenJDK不包含其餘的軟件包,好比Rhino Java DB JAXP等等。OpenJDK中能夠分離的軟件包都是儘可能的分離,可是這大多數都是自由軟件,能夠自行下載加入。
  • 不能使用Java商標:在安裝OpenJDK的機器上,輸入"java -version"顯示的是OpenJDK,可是若是是使用Icedtea補丁的OpenJDK,顯示的是java。

1.1.2 更多關於OpenJDK的事情

關於OpenJDK,還有一些事情須要瞭解。sql

  • OpenJDK項目:the OpenJDK project
  • Oracle's OpenJDK:基於OpenJDK項目源碼的,由Oracle 提供的,預先編譯好的JDK binaries。(不是Oracle JDK)
  • AdoptOpenJDK:基於OpenJDK項目源碼的,由OpenJDK community提供的預先編譯好的JDK binaries。

OpenJDK項目

目前Java的開發是以OpenJDK項目的形式進行的,而OpenJDK項目是徹底開源的(許可證是 GPLv2+CE,就是說你能夠根據OpenJDK的源碼開發本身的JDK,可是你的JDK也得要開源),該項目目前由Oracle主導,匯聚了社區的力量進行開發,IBM,紅帽等企業都有參與。在OpenJDK項目的官網上你能夠看到OpenJDK的源碼(包括JVM)與提交記錄等。apache

該項目只提供源碼,並無提供各個操做平臺(linux,windows,mac等)上的JDK binaries。bootstrap

Oracle's OpenJDK與AdoptOpenJDK

Oracle's OpenJDK與AdoptOpenJDK都是對OpenJDK項目的源碼進行build以後的產物,即JDK binaries。這二者只要版本相同就是同樣的,且二者均提供了不一樣操做系統(linux,windows,mac等)的binaries。但AdoptOpenJDK會提供更長(可能長達數年)的更新服務,而Oracle's OpenJDK只提供六個月的更新服務。所以建議使用AdoptOpenJDK,而不是Oracle's OpenJDK。windows

另外,Oracle's OpenJDK不是Oracle JDK。Oracle JDK是Oracle提供的付費版本的JDK,和Oracle's OpenJDK幾乎沒有區別,但Oracle JDK提供長時間的支持服務、安全更新等。api

只要不在生產環境下使用Oracle JDK或其餘商業版JDK,JAVA就仍然能夠無償使用。

1.1.3 其餘的JDK

事實上也能夠直接對OpenJDK的源碼進行build,來生成本身的JDK binaries,而後本身追蹤OpenJDK的源碼更新,本身打安全補丁。

對於那些對安全性穩定性要求很高,同時比較富裕的企業來講,也不必定要使用Oracle JDK。其餘的許多公司,好比阿里巴巴,亞馬遜,IBM等,也提供了本身版本的JDK binaries,他們或者也免費,或者有着不一樣的收費、更新週期等,能夠根據企業本身的實際須要來進行選擇。

例如Amazon Corretto,也是一個基於OpenJDK編譯的,採用GPL+CE協議開源的JDK。

1.2 關於Java版本

從2017年9月發佈Java 9開始,Oracle每六個月就會發佈一個新版本的JDK(具體來講是每一年的三月和九月),每三年會有一個LTS(Long Term Support release,長期支持)版本。Java 8 與 Java 11 爲當前提供支持的LTS版本。下一個LTS版本應該是Java 17。

下圖來自wiki-Java版本歷史:https://zh.wikipedia.org/zh-cn/Java%E7%89%88%E6%9C%AC%E6%AD%B7%E5%8F%B2

2020-05-09-17-50-32.png

Oracle JDK對LTS版本提供三年支持,而社區的AdoptOpenJDK承諾對LTS版本提供至少4年的支持。

1.3 JDK選擇與Java版本升級策略

咱們建議的策略是:

  1. 儘可能選擇OpenJDK,建議使用AdoptOpenJDK。
  2. 儘可能維持生產環境JDK版本穩定,建議選擇LTS版本。
  3. 根據LTS版本的支持時間,每三年或四年升級一次。

2、安裝AdoptOpenJDK

2.1 下載AdoptOpenJDK

AdoptOpenJDK下載網址:https://adoptopenjdk.net/

這個地址從國內訪問太慢了,能夠從清華大學提供的鏡像網站下載:

國內鏡像:https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/

2020-05-09-10-15-36.png

這裏下載的是OpenJDK11U-jdk_x64_linux_hotspot_11.0.7_10.tar.gz

關於JVM版本

AdoptOpenJDK目前能夠選擇的JVM有兩種。一種是原有的hotspot,另外一種是IBM開源的openj9。

目前一個簡單的評價是,openj9佔用的內存更少,但CPU密集任務方面不如hotspot。

就目前而言,通常開發與生產環境仍是推薦hotspot,其理論、JVM參數、命令行工具及性能調優的資料更豐富一些。
若是想切換到openj9,須要對其JVM的相關理論、參數、工具進行一些必要的調研。

2.2 linux安裝openJDK11

找個目錄存放下載好的openJDK11,如:/usr/java

解壓縮:

tar -zxvf OpenJDK11U-jdk_x64_linux_hotspot_11.0.7_10.tar.gz

若是你想安裝多個版本的JDK,下面這一步驟只在指定系統默認JDK版本時須要執行。

而後設置環境變量(編輯/etc/profile):

export JAVVA_HOME=/usr/java/jdk-11.0.7+10
export CLASSPATH=.:${JAVA_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

而後執行source /etc/profile,並確認java版本:java -version

3、Java8升級到Java11的注意事項

如下內容參考了文章:https://zhuanlan.zhihu.com/p/87157172

固然,Java版本升級是有風險的。例如從Java8升級到Java11的話,由於從Java9開始,JDK中去除了一些模塊,如JAXB和JAX-WS的相關依賴,對於這些去除的模塊,若是你的工程中用到了,那麼你須要單獨下載這些依賴包。

IBM提供了一個檢測工具,叫 Migration Toolkit for Application Binaries,能夠掃描應用程序二進制文件(.ear 或 .war 文件)並生成一份報告,突出顯示在應用程序中發現的潛在的 Java 11 問題。地址: https://developer.ibm.com/wasdev/downloads/#asset/tools-Migration_Toolkit_for_Application_Binaries。有興趣的同窗能夠自行下載學習。

下面是具體的一些事項:

3.1 準備JDK11的開發環境

  • IDE:更換支持JDK11的IDE,如 IDEA 2019.1
  • Maven:使用較新版本的Maven,如 maven 3.5 (Maven版本與IDE有時存在不兼容的狀況,會致使項目導入pom失敗,這裏的 IDEA 2019.1與Maven3.5是兼容的,而 IDEA 2019.1 與 Maven 3.6.3就有上述問題。)
  • Maven編譯插件:3.1.0以上 (不少資料說須要3.8以上,但其實並不須要,不少無效的目標發行版 11的現象實際上是maven工具或IDE中工程的jdk版本沒有選擇JDK11而致使的。)
  • FindBugs:已經再也不維護,建議替換爲SpotBugs
  • 等等...

3.2 字節碼處理相關依賴包的版本升級

因爲在Java 9 以後,每六個月版本會升級一次,若是你依賴的庫有處理Java字節碼相關的庫,應該注意下對應版本的升級。例如:

  • 對於直接操做字節碼的庫,若是你升級了JDK,那麼最好也跟着升級這些庫:ASM (7.0), Byte Buddy (1.9.0), cglib (3.2.8), or Javassist (3.23.1-GA).這些版本是OpenJDK11適用的版本。
  • 若是你使用的庫依賴了上面提到的操做字節碼的庫,那麼也須要注意下版本依賴,看依賴的操做字節碼的庫是否升級到了上面提到的版本。例如Spring Framework,須要採用5.1之後的版本,Springboot則須要2.1之後的版本。

3.3 Java9之後移除模塊的依賴對應

你能夠根據項目工程實際狀況,選擇添加獨立依賴,或者在依賴沒有衝突的狀況下,把下面全部依賴都添加上。

  • JavaBeans Activation Framework (JAF) (javax.activation),須要獨立引入,maven依賴以下:
<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>javax.activation</artifactId>
    <version>1.2.0</version>
</dependency>
  • JTA (java.transaction)變成了獨立依賴:
<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
</dependency>
  • JAXB和JAX-WS:
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>2.3.0</version>
    <type>pom</type>
</dependency>
  • Common Annotations:
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>
  • CORBA(java.corba)在JEP 230已經不復存在了,在你的項目中若是遇到,證實你的項目太古老了。移除掉想其餘辦法吧。

3.4 模塊可見性致使的內部API不能調用

Java9引入了模塊化,Java Platform Module System,java平臺模塊系統,簡稱JPMS。JPMS提供了一個模塊化平臺,使用來自Java語言規範的訪問控制概念來強制實施類型可訪問性封裝。每一個模塊都定義了哪些包將被導出,從而可供其餘模塊訪問。一個包能夠包含一個 API。若是模塊中的包未導出,則表示該模塊的開發人員不但願模塊外部使用這些包的API。若是外部仍然使用這些包,則會拋出錯誤!

對於這種錯誤,最好固然是更換其餘API。若是難以實現,則能夠經過添加編譯以及啓動參數解決。

  • --add-exports:模塊聲明中的exports語句將模塊中的包導出到全部或其餘模塊,所以這些模塊可使用該包中的公共API。 若是程序包未由模塊導出,則可使用--add-exports的命令行選項導出程序包:--add-exports <source-module>/<package>=<target-module-list>,若是設置target-module-list爲ALL-UNNAMED,那麼全部Classpath下的module,均可以訪問source-module中的pakage包下的公共API。
  • --add-opens:模塊聲明中的opens語句使模塊裏面的包對其餘模塊開放,所以這些模塊能夠在運行期使用深層反射訪問該程序包中的全部成員類型。 若是一個模塊的包未打開,可使用--add-opens命令行選項打開它。 其語法以下:--add-opens <source-module>/<package>=<target-module-list>,若是設置target-module-list爲ALL-UNNAMED,那麼全部Classpath下的module,均可以訪問source-module中的pakage包下的全部成員類型。

在編譯階段(javac),只須要添加--add-exports,對於執行階段(java),最好把--add-exports--add-opens都加上。同時,爲了明確全部須要添加的模塊和包,能夠經過添加--illegal-access=${value}來檢查。這個value能夠填寫:

  • permit: 將來可能會移除。僅在第一次反射調用內部api的時候報警
  • warn:每次反射調用內部api的時候報警
  • debug:在warn的基礎上,加上堆棧輸出
  • deny: 拒絕全部非法反射訪問內部api

能夠經過設置--illegal-access=deny來明確須要添加的全部--add-export--add-open包。

3.5 查找過時以及廢棄API以及對應的替換

經過JDK內置的jdeps工具查找過時以及廢棄API以及對應的替換:

jdeps --jdk-internals -R --class-path 'libs/*' $project

其中,libs是你的全部依賴的目錄,$project是你的項目jar包,示例輸出:

JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.misc.BASE64Encoder                   Use java.util.Base64 @since 1.8
sun.reflect.Reflection                   Use java.lang.StackWalker @since 9

一些在JDK11過時,可是JDK8使用的API:

  • sun.misc.Base64 (替換成 java.util.Base64)
  • com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel (替換成javax.swing.plaf.nimbus.NimbusLookAndFeel)
  • java.util.LogManager, java.util.jar.Pack200.Packer類 Unpacker: addPropertyChangeListener和removePropertyChangeListener這兩個方法已經移除
  • java.lang.Runtime類: methods getLocalizedInputStream 和 getLocalizedOutputStream方法已經移除
  • SecurityManager的操做方法已經總體移除

3.6 ClassLoader變化帶來的URLClassLoader的變化

Java 8的ClassLoader流程:

  1. bootstrap classloader加載rt.jar,jre/lib/endorsed
  2. ext classloader加載jre/lib/ext
  3. application classloader加載-cp指定的類

java9及以後的classloader流程:

  1. bootstrap classloader加載lib/modules
  2. ext classloader改名爲platform classloader,加載lib/modules
  3. application classloader加載-cp,-mp指定的類

同時,JDK9開始,AppClassLoader的父類再也不是 URLClassLoader了。這致使使用了AppClassLoader的熱部署或插件部署,如Spring-Boot的熱部署,會報異常:

Exception in thread "main" java.lang.ClassCastException: java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClassLoader
    at org.springframework.boot.devtools.restart.DefaultRestartInitializer.getUrls(DefaultRestartInitializer.java:93)
    at org.springframework.boot.devtools.restart.DefaultRestartInitializer.getInitialUrls(DefaultRestartInitializer.java:56)
    at org.springframework.boot.devtools.restart.Restarter.<init>(Restarter.java:140)
    at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:546)
    at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:67)
    at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:45)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:69)
    at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:292)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
    at com.asofdate.AsofdateMain.main(AsofdateMain.java:18)

對於動態加載的類,咱們在OpenJDK11中只能自定義類加載器去加載,而不是經過獲取APPClassLoader去加載。同時,這麼作也有助於你隨時能將動態加載的類卸載,由於並無加載到APPClassLoader。

建議使用自定義的類加載器繼承java.security.SecureClassLoader去加載類。

若是你想訪問classpath下的內容,你能夠讀取環境變量:

String pathSeparator = System.getProperty("path.separator");
String[] classPathEntries = System.getProperty("java.class.path").split(pathSeparator);

3.7 過時啓動參數修改

Java8到Java11有不少JVM參數變化。總的來講能夠總結爲兩類參數的變化:一是GC相關的,讓GC配置調優更加簡單;二是日誌相關的,日誌統一到了一塊兒,不像以前那麼混亂。

  • Java9 的JVM參數變換:打開https://docs.oracle.com/javase/9/tools/java.htm,搜索The following sections describe the options that are obsolete, deprecated, and removed
  • Java10 的JVM參數變換:打開https://docs.oracle.com/javase/10/tools/java.htm,搜索The following sections describe the options that are obsolete, deprecated, and removed
  • Java11 的JVM參數變換:打開https://docs.oracle.com/en/java/javase/11/tools/java.html,搜索The following sections describe the options that are obsolete, deprecated, and removed

每次的版本變化都須要關注如下三個部分:

  • Deprecated Java Options: 不推薦使用的參數,這些參數能夠被接受並執行,但會報警。
  • Obsolete Java Options: 過期的參數,這些參數能夠被接受但會被無視,同時會報警。
  • Removed Java Options: 移除的參數,使用這些參數會報錯。

這些不推薦的,過期的或移除的參數,若是有替代參數,請使用替代參數。

3.8 Lombok編譯異常

Java8升級到Java11後,lombok的版本須要升級到1.18以上。

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>

4、Maven對應Java升級到JDK11

在Java8升級到Java11的過程當中,咱們的本地編譯環境每每同時存在Java8與Java11兩套環境。
這裏說明一下在本地同時安裝有不一樣版本JDK的時候,如何讓Maven同時支持兩種Java版本的編譯。

4.1 本地Maven的全局配置中添加jdk11的profile

假定你已經在本地安裝了maven 3.5,在其conf/settings.xml中,添加新的profile配置:

<profiles>
  <!-- 原來的profile -->
  <profile>
    <id>jdk-1.8</id>
    <activation>
      <!-- 默認激活 -->
      <activeByDefault>true</activeByDefault>
      <jdk>1.8</jdk>
    </activation>
    ...
  </profile>
  <!-- 爲JDK11添加的profile -->
  <profile>
    <id>openJDK11</id>
    <activation>
      <jdk>11</jdk>
    </activation>
    <properties>
      <JAVA_HOME>/usr/java/jdk-11.0.7+10</JAVA_HOME>
      <JAVA_VERSION>11</JAVA_VERSION>
      <maven.compiler.source>11</maven.compiler.source>  
      <maven.compiler.target>11</maven.compiler.target>  
      <maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
    </properties>
    <repositories>
      <repository>
        <id>xxx-Repository</id>
        <name>xxx Maven Repository</name>
        <url>maven私服地址</url>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
      </repository>
    </repositories>
    <pluginRepositories>
      <pluginRepository>
        <id>xxx-Repository</id>
        <name>xxx Maven Repository</name>
        <url>maven私服地址</url>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
      </pluginRepository>
    </pluginRepositories>
  </profile>
</profiles>

4.2 IDEA中使用maven插件

若是你是在IDEA中直接用maven插件編譯,那麼:

1.首先確認項目相關JDK版本是否都已經指定爲JDK11:
2020-05-12-10-20-21.png
2020-05-12-10-20-48.png
2020-05-12-10-21-17.png

2.確認IDEA使用了本地maven,且對應的java版本是JDK11:
2020-05-12-10-52-51.png
2020-05-12-10-22-17.png

3.確認Maven插件使用的profile是前面新添加的openJDK11
2020-05-12-10-29-42.png

此時,你就可使用上圖中的Lifecycle下的各類maven命令了。

同時你能夠看到,maven-compiler-plugin的版本是3.1,並不須要升級到3.8:
2020-05-12-10-31-17.png

4.3 命令行直接使用mvn命令

若是你本地的環境變量JAVA_HOME仍然是以前的版本,好比jdk1.8,可是你又想直接在命令行使用mvn命令對工程進行編譯,那麼你須要在命令行會話窗口先臨時將JAVA_HOME改成JDK11,而後再執行mvn命令:

# 先cd到目標目錄
cd <工程目錄>

# 檢查mvn當前使用的java版本與Java home
mvn -version

# 改寫JAVA_HOME到jdk11安裝目錄
export JAVA_HOME=/usr/java/jdk-11.0.7+10

# 從新檢查mvn當前使用的java版本與Java home
mvn -version

# 確認java home已是JDK11之後,執行mvn命令
mvn clean install package

放心,在當前會話改寫JAVA_HOME並不會致使系統默認環境變量被改寫,僅對當前會話生效。

5、spring項目從Java8升級到Java11的對應

對於springMVC,springboot,springcloud的工程,Java8升級到Java11後,對應的spring版本也須要升級。

如下版本升級均採用maven工具

5.1 spring版本的選擇

根據Spring官方文檔的描述,Spring Framework 5.1.x 或 Spring Boot 2.1.x 開始才支持JDK11。

5.1.1 Spring Framework支持的JDK版本

https://spring.io/projects/spring-framework#learn選擇某個版本的Reference Doc.,而後選擇章節overview

或直接訪問地址:https://docs.spring.io/spring/docs/<版本號>/spring-framework-reference/overview.html#overview,注意把<版本號>替換爲具體的版本號如5.0.17.RELEASE5.1.15.RELEASE

  • 5.0.17.RELEASE :

2020-05-11-10-13-08.png

  • 5.1.15.RELEASE :

2020-05-11-10-13-40.png

由此可知,jdk11須要Spring Framework 5.1以上。

5.1.2 Spring Boot支持的JDK版本

https://spring.io/projects/spring-boot#learn選擇某個版本的Reference Doc.,而後選擇章節9. System Requirements

對於歷史版本,能夠直接訪問地址https://docs.spring.io/spring-boot/docs/<版本號>/reference/html/getting-started-system-requirements.html,注意把<版本號>替換爲具體的版本號如2.1.10.RELEASE2.0.8.RELEASE

  • 2.0.8.RELEASE :

2020-05-11-10-05-29.png

  • 2.1.10.RELEASE :

2020-05-11-10-05-56.png

由此可知,jdk11須要Springboot 2.1以上。

5.1.3 Spring Cloud版本

打開https://spring.io/projects/spring-cloud#overview,向下翻到Table 1. Release train Spring Boot compatibility:

2020-05-12-13-16-00.png

由此可知,Springcloud的Greenwich SR5與springboot的2.1.x是對應的。

springcloud關於對jdk11支持的說明

https://spring.io/projects/spring-cloud#learn中選擇某個版本的Reference Doc(這裏我選擇的是Greenwich SR5),點開選擇Single HTML,而後在文檔中,查找jdk相關章節,發現JDK 11 Support中有以下說明:
2020-05-11-10-19-32.png

即,jdk11後,springcloud的Eureka註冊中心須要單獨引入jaxb-runtime的依賴。

5.2 如何升級spring版本

對於springboot或springcloud項目來講,爲了解決依賴包的版本管理和版本衝突問題,通常不會直接在dependency中顯式地寫version,而是省略掉version,經過下面兩種方法,讓spring的版本項目幫咱們作版本管理。

一種是默認方式,經過parent標籤引入spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.14.RELEASE</version>
</parent>

另外一種方式是這裏推薦的寫法,採用dependencyManagement標籤,引入spring的版本兼容的依賴管理項目(經常使用的是spring-boot-dependenciesspring-cloud-dependencies):

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.14.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Cloud -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

注意

對於前面的章節[3.2 字節碼處理相關依賴包的版本升級],[3.3 Java9之後移除模塊的依賴對應]和[3.8 Lombok編譯異常],若是對應的依賴包已經寫進了pom的dependencies,那麼Java8升級到Java11以後,你能夠先肯定經過spring-boot-starter-parentspring-boot-dependenciesspring-cloud-dependencies所自動管理的依賴包版本是否已經包含了上述章節的依賴包,對應的版本是否已是支持JDK11的版本。

若是版本是unknown,說明spring-boot-starter-parentspring-boot-dependenciesspring-cloud-dependencies中沒有對應的依賴包版本管理,須要顯式地寫出version;若是有具體的版本號,則說明已經該依賴包已經集成到spring的依賴包版本管理中,你只須要確認該版本是否支持JDK11便可。

例如,pom以下:

...
    <properties>
        <spring-boot.version>2.1.10.RELEASE</spring-boot.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
...
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
...
        </dependencies>
    </dependencyManagement>

    <dependencies>
...
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
...
    </dependencies>

對應的lombok版本:
2020-05-11-13-34-16.png

5.3 其餘問題

  • mysql驅動包(mysql-connector-java)版本升級爲8.0.18後,對應驅動class變爲com.mysql.cj.jdbc.Driver

固然,你能夠選擇不升級mysql-connector-java的版本,好比保持在5.1.47版本,也是能夠的。此時driver-class-name仍然是com.mysql.jdbc.Driver

  • mybatis執行時發生報警:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/home/maven_repo/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar) to method java.lang.Integer.getChars(int,int,byte[])
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

mybatis-spring-boot-starter升級到新版本便可解決

<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
相關文章
相關標籤/搜索