将Spring Boot应用程序迁移到最新的Java版本(Java 11)

Migrating Spring Boot Applications to the Latest Java Version (Java 11)

最近,我们开始将应用程序从Java 8迁移到Java 11。 这是在Oracle宣布他们将在2019年初开始停止为Java 8提供商业支持之后。

我想限制本主题的范围,因为我将不详细讨论Java 11及其功能,但我将尝试在我们向Java和Java的最新版本迁移的背后提供高级解释。 此过渡涉及的步骤。

Java的发行周期

首先,我已经指出了为什么我们决定从Java 8迁移到Java 11.得知我们将在2019年初停止对Java 8的支持并且这将是公共更新的结束之后,最好迁移到最新版本。 Java版本,并随着新功能和安全更新而发展-然后讨论了要移植到哪个Java版本。

考虑到Oracle的发布周期(每6个月每3个月使用LTS发行一个新版本),我们认为最好将Java转换为具有商业生产版本的3年长期支持。

下图为我们提供了Oracle对即将到来的Java发布周期的计划的概述。

Image title

商业与 OpenJDK的

迁移之前会出现一些问题:

OpenJDK

第三方公司(例如IBM,RedHat和Azul)有许多开源JDK实现,它们正式支持JDK版本。 此外,Oracle支持OpenJDK,在GNU通用公共许可证下可以免费使用。 OpenJDK还具有许多组件,例如JVM Hotspot,JCL(Java类库),javac等。

支持方面有哪些新功能? 商业支持?

在Oracle决定采用新的破坏性发行节奏和许可之后,功能发行版的生命周期为六个月。 六个月后将不会提供更新,我们应该使用LTS版本三年,该版本只能由购买商业支持的人员使用。

我们可以使用OpenJDK进行生产吗?

您可以自费免费在生产中使用OpenJDK。 与通常会经常获得更新或补丁的商业版本相比,OpenJDK更新取决于实现者和发布者的发布时间。

订阅与Oracle的传统永久许可产品(例如Java SE Advanced)有何不同?

永久许可的软件需要支付前期费用,以及额外的年度支持和维护费用。 订阅以单一价格提供许可证,更新,升级和支持。 您只需要支付所需的费用和所需的时间(个人,非商业用途仍然免费,不需要订阅),

如果我使用容器平台或云会影响我吗?

每个用户(台式机)或处理器(服务器和/或云)都可以使用Java SE订阅。 您可以查看定价模型以准确了解和评估影响。

Oracle许可证定价

以下是Oracle发布的价格图表。 如果组织不准备按照Oracle的六个月发布计划进行频繁更新,则组织应根据这些定价模型提供预算。 使用此许可模型,在多核处理器上运行JDK可能会变得更加昂贵。

Image title

可以在此处找到Oracle产品的完整定价清单。

另外,您可以使用"用法跟踪器"来跟踪Java的用法。 这将有助于评估您的组织对Java的使用情况,并以此为基础来确定是使用许可版还是免费版Java。

另外,您可以免费使用第三方JDK甚至Oracle的OpenJDK版本。

对JDK 11的Spring支持

2018年9月某个时候,在SpringOne平台期间,宣布了Java 11的Spring Framework 5.1支持。 Spring Framework 4.3将支持最多Java 8,5.0将支持Java 9,而5.1将正式支持Java 11。

如果您使用的是Spring Boot,则从SpringBoot 2.1.X开始支持Java 11。 该计划计划从Spring Boot 2.2开始正式支持Java 12。 我们已经使用Java 11编译的代码将应用程序从Spring Boot 1.5.X迁移到Spring Boot 2.1.1。通过构建项目的微小更改,此操作很顺利。

另外,如果您将Pivotal或Cloud Foundry用于PaaS解决方案,则必须采取一些额外措施来部署Spring Boot 2.X.X版本。

Spring Boot 2.1使用Spring Framework 5.1,并且Spring已更新为所有依赖项的稳定版本。 因此,您可以在Spring Boot 2.1.1中正式使用Spring Starter并使用Java 11进行编译。

此外,如果使用Maven生成源代码,则需要将Maven编译器插件升级到> 3.5版本。

如果使用Gradle构建源代码,则需要将Gradle发行版升级到5.X版本。

其他依赖性,项目变更

由于Java 11已将许多库和依赖项外部化,因此我们必须向POM中显式添加一些依赖项。 使用JAXB,JAX-WS,JTA,JAVAX批注等J2EE模块的项目应显式添加依赖项并进行重建。 所有独立版本的J2EE都可以在Maven存储库或第三方站点中找到,因此Java SE排除了它们。

从Spring Boot 1.5.X迁移到Java 11 Spring Boot 2.1项目所要做的显着更改:

  • 如果您使用的是Eclipse IDE,请下载Eclipse photon或4.9

    如果您使用的是Eclipse IDE,请下载Eclipse photon或4.9

    从市场上为Eclipse IDE安装Java 11插件。

    对于Maven,将POM中的<java.version>更新为11,或者对于Gradle项目,将build.gradle中的sourceCompatibility更新为1.11。

    使用ASM(Java字节码库)将Maven编译器插件升级到3.8.0,或为Gradle项目下载gradle-5.0发行版。

    对于Coverage,因为不再支持Cobertura,所以从Cobertura移至Jacoco。

    更新Maven SureFire插件和FailSafe插件。

    如果您的项目中内置了单元测试(SureFire)和集成测试(FailSafe),请更新这些插件。 由于Maven具有不同的生命周期阶段,因此FailSafe插件有助于在集成测试阶段构建崩溃

    此外,在Maven项目中,您可以在命令行上设置系统JVM选项,例如"非法访问权限"

    由于Java中的强封装性使迁移变得困难,因此自Java 9起,默认情况下存在一些选项允许从类路径上的代码进行非法的反射访问。还有更多选项可以启用反射访问,例如" permit,warn,debug, 和"否认",您可以进行探索。

    Java 11支持TLS 1.3,它提供了显着的安全性和性能改进。

    类文件错误-任何对字节码进行操作的东西,例如cglib(3.2.8),ASM(7.0),Byte Buddy(1.9.0)或Javassist(3.23.1-GA)。 从Java 9开始,字节码级别每六个月增加一次,因此您必须定期更新类似的库。您可能会收到如下警告,最好将其更新为Java 11的Byte Buddy。

    1
    2
    3
    4
    5
    6
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by j9ms.internal.JPEG (file:...) to field com.sun.imageio.plugins.jpeg.JPEG.TEM
    WARNING: Please consider reporting this to the maintainers of j9ms.internal.JPEG
    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
    # here's the reflective access to the static field com.sun.imageio.plugins.jpeg.JPEG.TEM

  • 模块化:您还可以为您的应用程序创建JRE映像。 我们对应用程序进行了模块化,从而减少了内存占用,并在更大程度上优化了应用程序。

    模块化:您还可以为您的应用程序创建JRE映像。 我们对应用程序进行了模块化,从而减少了内存占用,并在更大程度上优化了应用程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <!-- Added for JAVA 11 Support START-->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.0</version>
      <configuration>
      <release>11</release>
      </configuration>
      <dependencies>
      <dependency>
        <!-- update compiler plugin dependency on ASM for Java 11 compatibility -->
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm</artifactId>
        <version>6.2</version>
      </dependency>
      </dependencies>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-SureFire-plugin</artifactId>
      <configuration>
        <argLine>
        --illegal-access=permit
        </argLine>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-FailSafe-plugin</artifactId>
        <configuration>
        <argLine>
        --illegal-access=permit
        </argLine>
      </configuration>
    </plugin>
    <!-- Added for JAVA 11 Support END-->

    Java 11引入了许多功能,我想限制本主题的范围,但是,仅仅为了使用最新版本的Java,探索,动手实践而不是移植总是更好的选择。

    结论

    Oracle希望加速Java的开发,而应用程序开发人员则期望经常进行更新。 为了满足这些要求,Oracle建议将Java转换为严格的基于时间的发布模式。 这意味着Java仍然可以在带有OpenJDK的生产环境中自由使用,但是如果您使用不支持Java 9+的框架或产品,则它可能不是使用OpenJDK 9以及更高版本的适合生产准备的解决方案。

    如标题所示,我只是专注于将Spring Boot Maven项目迁移到Java11。迁移中可能还有许多其他方面,例如安全性,JVM性能,证书,云就绪等。请随时对您的发现发表评论。 !

    其他资源

    https://www.oracle.com/technetwork/java/java-se-support-roadmap.html

    https://www.oracle.com/technetwork/java/javaseproducts/overview/javasesubscriptionfaq-4891443.html

    https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-with-Java-9-and-above

    https://www.oracle.com/technetwork/java/javase/javaclientroadmapupdate2018mar-4414431.pdf