升级Java17问题记录

木小丰 2021年09月18日 1,124次浏览

最新的长期支持版Java17于2021年9月14日如期发布,按照发布规划,JDK/Java 17 属于长期支持版本 (LTS),将会获得 8 年的技术支持,直至 2029 年 9 月。值得一提的是,根据 Oracle 最新推出的**「Free Java License」**,Oracle JDK 可免费用于生产环境。

Java各版本新特性请查看以下系列文章:Java17的新特性

原文链接,转载请注明出处

1、Lombok报错

错误日志:

class lombok.javac.apt.LombokProcessor (in unnamed module @0x3b968111) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module @0x3b968111

错误原因没有深入分析,直接升级到最新版本解决:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

2、模块化(Jigsaw)报错

错误日志:

module java.base does not "opens java.lang" to unnamed module @1941a8ff

错误原因是在Java9中引入了模块化功能:The State of the Module System,常见的库比如(Spring、Hibernate、JAXB)大量用到包扫描和反射,所以常出现此错误。一个粗暴的解决办法是将没开放的module强制对外开放,即保持和Java9之前的版本一致。

开放模块有以下两种模式:

  • --add-exports 该包将被导出,这意味着在编译和运行时可以访问其中的所有公共类型和成员。
  • --add-opens 包被打开,这意味着所有类型和成员(不仅仅是公共成员!)都可以在运行时访问。

如果使用的代码中使用了诸如setAccessible(true)的方法,就选择 --add-exports。想了解更多请参考:What's the difference between --add-exports and --add-opens in Java 9?

针对这个错误,Java命令行添加以下命令:

--add-opens java.base/java.lang=ALL-UNNAMED

改完后的效果类似这样:

java --add-opens java.base/java.lang=ALL-UNNAMED -jar demo.jar

3、zookeeper连接报错

错误日志:

org.apache.zookeeper.ClientCnxn - Session 0x0 for server 10.0.*.*/<unresolved>:2181, unexpected error, closing socket connection and attempting reconnect
java.nio.channels.UnresolvedAddressException: null
	at sun.nio.ch.Net.checkAddress(Net.java:149) ~[?:?]
	at sun.nio.ch.Net.checkAddress(Net.java:157) ~[?:?]
	at sun.nio.ch.SocketChannelImpl.checkRemote(SocketChannelImpl.java:816) ~[?:?]
	at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:839) ~[?:?]
	at org.apache.zookeeper.ClientCnxnSocketNIO.registerAndConnect(ClientCnxnSocketNIO.java:277) ~[zookeeper-3.4.13.jar:3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03]
	at org.apache.zookeeper.ClientCnxnSocketNIO.connect(ClientCnxnSocketNIO.java:287) ~[zookeeper-3.4.13.jar:3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03]
	at org.apache.zookeeper.ClientCnxn$SendThread.startConnect(ClientCnxn.java:1021) ~[zookeeper-3.4.13.jar:3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03]
	at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1064) [zookeeper-3.4.13.jar:3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03]

原因分析:

Java15中InetSocketAddressHolder的toString方法有重构:

image-20210918202119549

下面是之前的版本:

image-20210918202301690

而在zookeeper的3.4的版本中直接使用 InetSocketAddress的toString()方法,因为Java新版本的hostname中加入/后缀导致创建连接失败。

修复方案是升级zookeeper的jar包为大于等于3.5的版本

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.5.9</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>*</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4、总结

本博客总结了Java11升级到Java17过程中遇到的问题,如果读者现在使用的是Java8,可以参考作者文章:JDK8升级JDK11过程记录,你在升级Java新版本过程中还遇到过什么问题? 欢迎留言讨论。

附录:

Oracle JDK下载链接:https://www.oracle.com/java/technologies/downloads/

OpenJDK下载链接:https://jdk.java.net/17/


本文作者:木小丰,美团Java高级工程师,关注架构、软件工程、全栈等,不定期分享软件研发过程中的实践、思考。欢迎关注公共号:Java研发