问题
java 或者 scala开发中一个比较蛋疼的问题,jar包冲突,有时会表现出找不到类,报类似下面的错误:
java.lang.NoSuchMethodError:org.apache.thrift.protocol.TBinaryProtocol$Factory.(ZZJJ)V
整理一下排查问题的方法和思路
1.报错类是否存在
首先看一下找不到的类在ide里是不是可以导到这个包:
import org.apache.thrift.protocol.TBinaryProtocol
如果标红那么说明没有这个依赖,去查一下这个依赖的maven配置在pom文件里加一下
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>thrift</artifactId>
<version>0.5.0</version>
</dependency>
2.依赖冲突
如果能找到这个类,也有这个包,但是依赖了别的包也依赖这个包而且版本不一致怎么办?
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.11</artifactId>
<version>3.0.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</exclusion>
</exclusions>
</dependency>
当然是exclusion。但是怎么知道在哪exclusion,有没有exclusion干净怎么办?
推荐一个idea插件:maven helper
安装完这个插件,pom文件有一个选项Dependency Analyzer
这个界面可以看到依赖关系并且可以很方便的exclusion
3.mvn命令
一些mvn命令可以辅助我们查找问题。
- mvn dependency:tree 这个命令可以看到依赖关系
- mvn package -X 这命令可以打包的同时看到完整的打包过程
4.反编译jar包
还有一种简单粗暴的方式,就是看看我们的jar包里路径下到底有没有这个类,这个类到底以后没有这个方法
解压出class
反编译命令
javap -c -l xxx.class
5.环境lib包冲突
是否是包依赖的第三方jar包和集群jar包版本冲突了?
比如mr或者spark任务jar包里有这个包,集群也有这个包,版本不一致,用的谁的?
以mr任务为例,可以使用这个参数设置优先使用用户自己的包而不是集群的包
conf.set("mapreduce.job.user.classpath.first", "true");
conf.set("mapreduce.task.classpath.user.precedence", "true");
spark,tomcat之类的也是一个思路
总结
no such class 和 no such method是个常见的ex,有时一分钟可以解决,有时可能找一天都没找到问题,还是需要多种方式多种思路面对不同的场景哇