栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java - java.lang.NoSuchMethodError: xxx 错误详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java - java.lang.NoSuchMethodError: xxx 错误详解

一.引言

本地执行 java -classpath $jar $class 时报错:

java.lang.NoSuchMethodError: 
com.alibaba.fastjson.JSONObject.getOrDefault
(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object

可是 $jar 内 maven 配置已打入 fastJson 依赖且未 Provided:

        
            com.alibaba
            fastjson
            1.2.76
         

于是开始踩坑之旅。

二.问题分析
      val json = JSON.parseObject(info)
      val array = JSON.parseArray(json.getOrDefault("data", "[]").toString).toArray().map(_.toString)

我的代码大致为 Json 解析,先解析 Object 再解析 array,由于报错位置提示为 noSuchMethod: getOrDefault,所以说明 json.parseObject 这行执行没有问题,即 fastJson 依赖正常打入,所以可以判断不是因为 maven 未打入依赖造成。所以可能是如下问题:

jar 包冲突: 多个项目都存在 fastJson 依赖,代码读取了低版本的 fastJson,低版本无该方法导致调用失败。这里其实涉及一个常识问题,如果报错 NoClassDefFound 报错,那么大概率是打包失败或者未提供相关 jar 包,而 noSucnMethod 报错除了方法名写错的低级失误外,大部分是 jar 包冲突导致。

三.问题解决 1.存在高低版本 Jar 包

A.jar-fastJson 低版本,B.jar-fastJson 高版本,本地执行程序读取低版本 fastJson 有可能导致上述问题,所以需要排查的是 jar 包中哪些项目包含了 fastJson:

这里可以使用 java -verbose:class,该方法会在控制台打印程序运行加载的类的情况,使用该命令即可查看程序内哪些依赖包含 fastJson,然后再去对应项目查找是否高低版本。

java -verbose:class -classpath your.jar your.class

执行后 cat log | grep fastJson 即可看到 fastJson 的文件来自于哪个 jar 包,后方红色标识即为来源:

经过检查,所有 fastJson 类文件均加载于同一 jar 包,即我本身的项目 jar 包依赖,所以排除高低版本问题。

Tips:

这里查看项目依赖采用了 -verbose 方法,该方法除了打印 jvm 运行时加载依赖,也可以传入 gc 或者 jni 查看虚拟机响应,其次也可以借助 maven :

mvn -Dverbose dependency:tree

该方法可以按层次打印出jar包相关依赖于版本,可以更好地方便定位 jar 包方法冲突与版本冲突,有需要可以参考我之前的文章: java.lang.NoSuchMethodError 之 依赖冲突解决方案,之前写作本文主要是线上任务出现该报错,本文主要是在本地执行 java 任务报错,所以虽然场景不同,但是报错相同,两篇文章的方法都可以借鉴到排查该方法背后的 jar 包冲突。

 

2.maven 依赖存在问题

既然不是高低版本问题,那就定位到唯一 jar 包,我怀疑是 maven 打包异常,所以决定 provided 该依赖,随后从外部传入。

首先注释掉 jar 包中的 fastJson 依赖:

        
            com.alibaba
            fastjson
            1.2.76
            provided
        

随后本地执行传入 fastJson 依赖,本地传入依赖可以使用 -Djava.ext.dirs 参数,该方法指定一个路径文件夹,文件夹下包含所以项目需要的额外依赖,有点类似项目中的 lib 文件夹:

java -verbose:class -Djava.ext.dirs=$dir -classpath your.jar your.class

这里在本地创建一个文件夹放入 fastJson 依赖即可:

 

 

再次执行任务,依旧出现同样问题,因此唯一 jar 包的问题也不存在了。

3.Java 环境问题(解决  )

方法1高低版本排除了多 jar 包的情况,方法二单独 provided 排除了单 jar 包的情况,所以剩下的只剩环境问题了,回想起刚才 -verbose 打印的日志,java 版本都是 1.7.0:

 

查看本地 Java 环境:

echo $JAVA_HOME
/usr/local/jdk1.8.0_131

原来是 java 版本不匹配,修改提交脚本再次尝试,问题解决:

$JAVA_HOME/bin/java -classpath your.jar your.class

 

四.总结

这个问题困扰了一天,期间多半时间花在 maven 打包问题排查与 fastJson 依赖冲突的问题上,但是结果是最基本的 java 环境不匹配问题。今日踩坑,明日避坑,虽然期间尝试了多种方法最终解决方法如此简单,但是找到简单方法过程中,熟悉了不同的 jar 包冲突分析方法,后续再有类似问题也可以更快的定位和解决,所以还是收获满满,可能这就是学习的魅力吧,最后希望大家都可以少点 bug ~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/677582.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号