NoSuchMethodError 与 jar包加载的位置顺序



一个基于SpringBoot的 Flink程序(FlinkListener.jar),在Windows 8系统 和 在自己的Linux虚拟机上运行正常, 把 jar 包上传到局域网Linux服务器上,提示 NoSuchMethodError错误
Caused by: java.lang.NoSuchMethodError: com.mysql.cj.CharsetMapping.getJavaEncodingForMysqlCharset(Ljava/lang/String;)Ljava/lang/String;
        at io.debezium.connector.mysql.MySqlValueConverters.charsetFor(MySqlValueConverters.java:331) ~[debezium-connector-mysql-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.connector.mysql.MySqlValueConverters.converter(MySqlValueConverters.java:298) ~[debezium-connector-mysql-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.TableSchemaBuilder.createValueConverterFor(TableSchemaBuilder.java:400) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.TableSchemaBuilder.convertersForColumns(TableSchemaBuilder.java:321) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.TableSchemaBuilder.createValueGenerator(TableSchemaBuilder.java:246) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.TableSchemaBuilder.create(TableSchemaBuilder.java:138) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.RelationalDatabaseSchema.buildAndRegisterSchema(RelationalDatabaseSchema.java:130) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at io.debezium.relational.HistorizedRelationalDatabaseSchema.recover(HistorizedRelationalDatabaseSchema.java:52) ~[debezium-core-1.5.4.Final.jar!/:1.5.4.Final]
        at com.ververica.cdc.connectors.mysql.debezium.task.context.StatefulTaskContext.validateAndLoadDatabaseHistory(StatefulTaskContext.java:163) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at com.ververica.cdc.connectors.mysql.debezium.task.context.StatefulTaskContext.configure(StatefulTaskContext.java:114) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at com.ververica.cdc.connectors.mysql.debezium.reader.SnapshotSplitReader.submitSplit(SnapshotSplitReader.java:93) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at com.ververica.cdc.connectors.mysql.debezium.reader.SnapshotSplitReader.submitSplit(SnapshotSplitReader.java:64) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at com.ververica.cdc.connectors.mysql.source.reader.MySqlSplitReader.checkSplitOrStartNext(MySqlSplitReader.java:163) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at com.ververica.cdc.connectors.mysql.source.reader.MySqlSplitReader.fetch(MySqlSplitReader.java:73) ~[flink-connector-mysql-cdc-2.2.1.jar!/:2.2.1]
        at org.apache.flink.connector.base.source.reader.fetcher.FetchTask.run(FetchTask.java:56) ~[flink-connector-base-1.13.3.jar!/:1.13.3]
        at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.runOnce(SplitFetcher.java:140) ~[flink-connector-base-1.13.3.jar!/:1.13.3]
        at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.run(SplitFetcher.java:103) ~[flink-connector-base-1.13.3.jar!/:1.13.3]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_151]

查看 FlinkListener.jar 包中的lib目录下是否有相关mysql依赖

[root@jenkinspc25 tools]# jar -tvf FlinkListener.jar | grep mysql.*.jar
251194 Tue Apr 26 19:08:40 CST 2022 BOOT-INF/lib/flink-connector-mysql-cdc-2.2.1.jar
370666 Thu Jul 01 01:03:16 CST 2021 BOOT-INF/lib/debezium-connector-mysql-1.5.4.Final.jar
192762 Tue Apr 20 16:13:28 CST 2021 BOOT-INF/lib/mysql-binlog-connector-java-0.25.1.jar
2397321 Tue Jun 16 17:17:36 CST 2020 BOOT-INF/lib/mysql-connector-java-8.0.21.jar

而报错提示的 CharsetMapping 类在 mysql-connector-java-8.0.21.jar 依赖中.


使用 -XX:+TraceClassLoading 查看类的加载情况
java -XX:+TraceClassLoading -jar FlinkListener.jar > FlinkListener.log &

查看 FlinkListener.log 文件, 定位到 CharsetMapping 关键字

在这里插入图片描述CharsetMapping 这个类是从 /home/java/jre/lib/ext/mysql-connector-java-8.0.27.jar 加载的, 并不是从 FlinkListener.jar!/BOOT-INF/lib 目录下加载 .

天真的以为, 把 /home/java/jre/lib/ext 目录下的 mysql-connector-java-8.0.27.jar 名称改成 mysql-connector-java-8.0.27.jar.remove 就可以, 哪知道它依然会从 mysql-connector-java-8.0.27.jar.remove 加载,如下所示
在这里插入图片描述通过 file 命令查看, 它的确还是JAR类型 (不能以貌取人,不能以貌判断一个文件的类型)

[root@localhost ext]# file mysql-connector-java-8.0.27.jar.remove 
mysql-connector-java-8.0.27.jar.remove: Java archive data (JAR)

【解决方案】
1.直接移除 /home/java/jre/lib/ext 目录下的 mysql-connector-java-8.0.27.jar 包. 但可能会影响其它的程序
2.在不移除 mysql-connector-java-8.0.27.jar 包的前提下, 将 mysql-connector-java-8.0.21.jar 包也拷贝到 /home/java/jre/lib/ext 目录. 虽然两个版本的包都在同一个目录下, 但不表示JVM在启动的时候会按照 ls -l 命令展示的顺序加载, JVM会按照Linux文件系统的规则加载同一目录下的jar包, 如何让JVM一定会加载同一目录下的 mysql-connector-java-8.0.21.jar 文件, 可以参考另一篇文章 NoSuchMethodError 与 Linux系统读取目录内文件顺序 .



【参考外链】
1.类加载顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值