摸石头过Java & scala & spark [1]

在使用Java、Scala和Spark时遇到`java.lang.NoSuchMethodError`异常,初步判断为版本不匹配问题。尝试更换Scala版本未果,接着发现Jackson版本不兼容,调整后仍报错。通过`mvn dependency:tree`命令查找间接依赖,发现`drools-compiler`中的`janino.jar`版本冲突。最终解决办法是定位并更新冲突的JAR包版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Exception in thread “main” java.lang.NoSuchMethodError: org.codehaus.janino.ClassBodyEvaluator.setExtendedClass(Ljava/lang/Class;)V
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator.org.orgapachesparksparksqlcatalystcatalystexpressionscodegencodegenCodeGenerator$$doCompile(CodeGenerator.scala:949)

看到 java.lang.NoSuchMethodError直觉就是版本问题,但是问题是不知道是哪个版本的问题。

怀疑是因为本地scala是2.11.12版本
重新装一个2.11.8版本试试
还是不行

换来回去,改出一个新错

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Incompatible Jackson version: 2.8.9

改成2.4告诉我 Jackson version: 2.4.0 to old
Jackson 大哥你到底要啥version呢

最后答案在spark目录下的jars
把version换成了一样的2.6.5

最后定位到janino.jar
pom已经改为了跟spark jars 一致的版本

<dependency>
        <groupId>org.codehaus.janino</groupId>
        <artifactId>janino</artifactId>
        <version>3.0.8</version>
</dependency>

还是报错
最后怀疑是其他依赖包冲突

查看jar包间接依赖

mvn dependency:tree>tree.txt

[INFO] +- org.drools:drools-compiler:jar:5.0.1:compile
[INFO] | +- org.antlr:antlr-runtime:jar:3.1.1:compile
[INFO] | +- org.eclipse.jdt:core:jar:3.4.2.v_883_R34x:compile
[INFO] | - janino:janino:jar:2.5.15:compile

定位到org.drools:drools-compiler

<dependency>
    <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <version>5.0.1</version>
            <exclusions>
                <exclusion>
                    <groupId>janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
            </exclusions>
</dependency>

JAR包冲突解决方法

问题表现

系统原来可以运行, 但是引入某个jar包(为了调用某个服务)后, 所有配置/参数都正确, 但是却运行不起来, 或者报找不到类, 找不到方法等异常!
java类找不到 java.lang.ClassNotFoundException
方法不存在 java.lang.NoSuchMethodError
字段不存在 java.lang.NoSuchFieldError
类错误 java.lang.LinkageError
表面原因

war包中jar包和服务器上jar包冲突, 由于现在服务器功能越来越强大, 而引入的jar也在不断增加, 出现的冲突的可能性也越来越大, 而且正式环境复杂, 而且不能轻易修改服务器相关配置
根本原因

同一个java类存在多个jar包或类路径中, 而这大多由于使用了不同jar包版本造成.
maven管理jar包, 如果同一个Jar有多个版本是根据最短路径拉取jar包的
同一个package出现在多个jar包里面, 怎么处理?
简单的处理方法

根据报错的class名或方法名定位到可能导致冲突的jar包,jar包冲突引入有几种情况:
引入了这个jar包的多个版本,而mvn仲裁的时候取了错误的版本,这个版本本身就缺少正确的class或方法。
引入了不同坐标但是具有同名class的多个jar,mvn加载class的顺序差异会导致加载到错误的class。
通过mvn dependency:tree > tree.txt 导出全部的依赖。 可以使用 -Dverbose 、-Dincludes或者-Dexcludes参数来精确定位导致冲突的jar包。
找到需要排除的依赖jar包,通过mvn仲裁优先的方法定义正确的jar包,或者通过exclusion的方式排除错误的jar包。
温馨提示:另外在项目开发中jar尽量按需引入,系统管理起来,别什么都不管直接加包进来,这样也可以在一定程度上减少jar包冲突的风险。
避免技巧

为了减少jar包冲突, 特别是一些底层jar包, 根据最短路径方法: 最好人工指定版本, 并使用dependencyManage
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值