指南:Java 17(升级版)

本文主要分为以下几个部分:

  • 编译相关
  • 参数迁移相关
  • 运行相关

编译相关

JEP 320

在 Java11 中引入了一个提案 JEP 320: Remove the Java EE and CORBA Modules (openjdk.org/jeps/320) 提案,移除了 Java EE and CORBA 的模块,如果项目中用到需要手动引入。比如代码中用到了 javax.annotation.* 下的包:

import javax.annotation.PreDestroy;
public abstract class FridayAgent 
    @PreDestroy
    public void destroy() {
        agentClient.close();
    }
}    
复制代码

在编译时会找不到相关的类。这是因为 Java EE 已经在 Java 9 中被标记为 deprecated,Java 11 中被正式移除,可以手动引入 javax 的包:

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
复制代码

使用了 sun.misc.* 下的包

比如 sun.misc.BASE64Encoder,这个简单,替换一下工具类即可。

[ERROR]   symbol:   class BASE64Encoder
[ERROR]   location: package sun.misc
复制代码

netty 低版本使用了 sun.misc.*,编译错误信息如下

Caused by: java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0
        at io.netty.util.internal.PlatformDependent.getSystemClassLoader(PlatformDependent.java:694) ~[netty-all-4.0.42.Final.jar!/:4.0.42.Final]
复制代码

对应的源码如下:

/**
 * The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}.
 */
final class PlatformDependent0 {
}

https://github.com/netty/netty/issues/6855
复制代码

lombok 使用了 com.sun.tools.javac.* 下的包

错误信息如下:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.2:compile (default-compile) on project encloud-common: Fatal error compiling: java.lang.ExceptionInInitializerError: Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not "opens com.sun.tools.javac.processing" to unnamed module

如果你的项目中使用 lombok,而且是低版本的话,就会出现,lombok 的原理是在编译期做一些手脚,用到了 com.sun.tools.javac 下的文件,升级到最新版可以解决。ps,个人很不喜欢 lombok, 调试的时候代码和 class 对不上真的很恶心。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
   <!-- <version>1.16.4</version>-->
    <version>1.18.24</version>
</dependency>
复制代码

kotlin 版本限制

我们后端在很多年前就 all-in Kotlin,Kotlin 的升级也是我们的重中之重。

[ERROR] Failed to execute goal org.jetbrains.kotlin:kotlin-maven-plugin:1.2.71:compile (compile) on project encloud-core: Compilation failure [ERROR] Unknown JVM target version: 17 [ERROR] Supported versions: 1.6, 1.8

Kotlin 在 1.6.0 版本开始支持 Java17 的字节码,低于 1.6.0 的编译会直接报错

废弃依赖分析

可以用 jdeps --jdk-internals --multi-release 17 --class-path . encloud-api.jar 来做项目的依赖分析

这样你就可以知道哪些库需要做升级了。

参数迁移

什么是 Unified Logging

在 Java 领域,有广为人知的日志框架,slf4j、log4j 等,这些框架提供了统一的编程接口,让用户可以通过简单的配置实现日志输出的个性化配置,比如日志 tag、级别(info、debug 等)、上下文(线程 id、行号、时间等),在 JVM 内部之前一直缺乏这样的规范,于是出来了 Unified Logging,实现了日志格式的大一统,这就是我们接下来要介绍的重点 Unified Logging

我们接触最多的是 gc 的日志,在 java8 中,我们配置 gc 日志的参数是 -Xloggc:/tmp/gc.log。在 JVM 中除了 GC,还有大量的其它相关的日志,比如线程、os 等,在新的 Unified Logging 日志中,日志输出的方式变更为了 java -Xlog:xxx,GC 不再特殊只是做为日志的一种存在形式。

java -Xlog -version
复制代码

输出结果如下:

可以看到日志输出里,不仅有 GC 相关的日志,还有 os 线程相关的信息。事实上 java 的日志的生产者有非常多部分,比如 thread、class load、unload、safepoint、cds 等。

归根到底,日志打印,需要回答清楚三个问题:

  • what:要输出什么信息(tag),以什么日志级别输出(level)
  • where:输出到哪里(console 还是 file)
  • decorators:日志如何

输出什么信息(selectors)

首先来看 what 的部分,如何指定要输出哪些信息,这个在 JVM 内部被称之为 selectors。

JVM 采用的是 <tag-set>=<level>的形式来表示 selectors,默认情况下,tag 为all,表示所有的 tag,level 为 INFOjava -Xlog -version 等价于下面的形式

java -Xlog:all=info -version
复制代码

如果我们想输出tag 为 gc,日志级别为 debug 的日志,可以用 java -Xlog:gc=debug 的形式:

$ java -Xlog:gc=debug -version
[0.023s][info][gc] Using G1
[0.023s][debug][gc] ConcGCThreads: 3 offset 22
[0.023s][debug][gc] ParallelGCThreads: 10
[0.024s][debug][gc] Initialize mark stack with 4096 chunks, maximum 524288
复制代码

这样就输出了 tag 为 gc,级别为 debug 的日志信息。

不过这里有一个比较坑的点是,这里的 tag 匹配规则是精确匹配,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值