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>
相关文章
相关标签/搜索