轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

    • 核心

    • 并发

    • 经验

      • Java8升级到Java11的实践
        • 为什么升级?Java 8不好用了么
          • 为何不直接升级到Java 17?
          • 模块系统
          • 统一JVM日志
          • 软件包的升级
          • 1、javaassist包,CtClass.toClass()调用方式的变化
          • 2、Security.removeProvider引发的javax.net.ssl.SSLProtocolException: Cannot decode named group: x25519
          • 3、MethodHandler API在不同版本的表现
          • JVM参数变化
        • 总结
      • Java 11升级到Java17,以及升级到Spring Boot 3的过程
    • JVM

    • 企业应用

  • Spring

  • 其他语言

  • 工具

  • 后端
  • Java
  • 经验
轩辕李
2023-01-06
目录

Java8升级到Java11的实践

# 为什么升级?Java 8不好用了么

升级Java版本主要有两方面考虑:

  • 一个是高版本提供了更丰富的便利性、更高的性能、更全面的安全性。详情见:Java历代版本新特性 9-11部分
  • 一个是Spring Boot 3.x开始,只支持Java 17+了

# 为何不直接升级到Java 17?

为何不直接升级到Java 17,因为风险太大。比如Java 15移除了Nashorn JavaScript脚本引擎。
还有就是一些主流的框架暂时还未完全支持Java 17,比如dubbo。

# 如何升级?

首先,我们需要注意到已经删除的功能,包括:

  • JavaFX。从Java 11开始,该平台不再包含JavaFX作为规范的一部分,并且大多数JDK构建都将其删除。您可以使用来自 Gluon 的单独 JavaFX 构建,也可以将 OpenJFX 依赖项添加到您的项目中。
  • 字体。曾几何时,JDK包含一些字体,但从Java 11开始,它们被删除了。例如,如果您使用Apache POI(用于Microsoft Office兼容文档的Java API),您将需要字体。操作系统需要提供字体,因为它们不再存在于 JDK 中。但是,在 Alpine Linux 等操作系统上,必须使用该 apt install fontconfig 命令手动安装字体。根据您使用的字体,可能需要额外的包。
  • Java Mission Control。Java Mission Control 曾经包含在 JDK 中,但现在它可以以新名称作为单独的下载提供:JDK Mission Control。
  • CORBA模块。Java的CORBA模块没有正式的替代品,该模块在Java 11中被删除。但是,Oracle GlassFish Server 包含 CORBA 的实现。

其次,要了解Java 9到Java 11 之间的版本新特性,可以参考上面的文章。

个人认为重中之重是Java 9模块系统和JVM统一日志。不了解模块系统,就会对反射API的各种错误抓狂;不了解统一JVM日志,就分析不了GC的状况。

# 模块系统

关于模块系统,参考:Java 模块系统 (opens new window)
这里补充一下--illegal-access参数,因为模块化的关系,如果模块中的软件包未导出或打开,但你仍然要使用这些软件包,可能会面临破坏应用程序的风险。如果在运行期反射调用内部API,可以通过添加--illegal-access=${value}来检查,它有四个值:

  • permit: 未来可能会移除。仅在第一次反射调用内部api的时候报警
  • warn:每次次反射调用内部api的时候报警
  • debug:在warn的基础上,加上堆栈输出
  • deny: 拒绝所有非法反射访问内部api

要注意Java 17中--illegal-access的默认值为deny,且不允许修改。
所以使用Java 11的时候有两种选择:

  1. 使用默认值,不做任何配置。那么只会在第一次反射内部API的时候报警
  2. 为了以后更方便的升级Java 17,对于某些模块,手动打开开放的开关。比如JVM启动参数中增加--illegal-access=deny --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED

# 统一JVM日志

参考此篇文章:Java 9 平台和JVM日志 (opens new window)
项目线上配置:

-Xlog:gc*,safepoint:/data/logs/jvm/app-gc.log:time,uptime:filecount=2,filesize=200M

# 软件包的升级

三方包的Java 11兼容也是一个大问题,这里仅对我遇到的情况做一个记录。

# 1、javaassist包,CtClass.toClass()调用方式的变化

CtClass类实例生成的调用方式从.toClass(classloader, neighborClass.getProtectionDomain())变为.toClass(neigborClass),可以参考:issues 369 (opens new window)

# 2、Security.removeProvider引发的javax.net.ssl.SSLProtocolException: Cannot decode named group: x25519

这个错误实在令人费解,最后在Java 11 Migration (opens new window) 中找到了答案,搜索到三方包中有这么一行代码:Security.removeProvider("SunEC");,非常无语。
解决方案是升级三方包。

# 3、MethodHandler API在不同版本的表现

项目中主要是反射调用接口的default方法,在不同的Java版本中,调用方式也不同。
参考:反射调用默认方法在Java 8/9/10中的不同变现 (opens new window)

# JVM参数变化

可以在官网上查看9-11的JVM参数变化:

  • Java 9 Deprecated Java Options (opens new window)
  • Java 10 Deprecated Java Options (opens new window)
  • Java 11 Deprecated Java Options (opens new window)

不过这样并不是高效的做法,你可以直接通过java -XX:+PrintCommandLineFlags ... -version来检测原先的JVM参数是否可用,或者通过这个网站来检测:JaCoLine (opens new window)

# 总结

我们分析了Java版本升级的必要性,对于版本升级过程中的主要步骤和事项进行了说明,希望对你有用!

祝你变得更强!

编辑 (opens new window)
上次更新: 2023/07/12
Java并发-调试与诊断
Java 11升级到Java17,以及升级到Spring Boot 3的过程

← Java并发-调试与诊断 Java 11升级到Java17,以及升级到Spring Boot 3的过程→

最近更新
01
Spring Boot版本新特性
09-15
02
Spring框架版本新特性
09-01
03
Spring Boot开发初体验
08-15
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式