报错情景:
使用Mibble对mib文件进行解析,在使用MibLoader对mib文件进行load时,出现错误:
错误:
java.lang.NoSuchMethodError: net.percederberg.mibble.asn1.Asn1Parser.reset(Ljava/io/Reader;Lnet/percederberg/grammatica/parser/Analyzer;)V
at net.percederberg.mibble.MibLoader$MibSource.parseMib(MibLoader.java:970)
at net.percederberg.mibble.MibLoader.loadQueue(MibLoader.java:724)
at net.percederberg.mibble.MibLoader.load(MibLoader.java:550)
at net.percederberg.mibble.MibLoader.load(MibLoader.java:479)
比较奇怪的是,在另一个class另一个类型启动下可以正常运行:
单独新建一个test类,在test类中的main方法里使用同样功能代码时,正常运行,无报错。
分析
1、打断点,逐步进入代码调用链,发现是load的loadQueue函数出错
2、逐步进入,是其中的parseMib出错
主要问题是parser,主要出错在此处的reset函数
3、主要为在new Asn1Parser初始化之后进行的第二次parser的判断,然后进入到执行reset函数时出错,对于直接执行main方法,和作为web的service调用,对比二者此处开始初始化的parser的值:
对比无差异,排除初始化的parser不同的原因:
4、ctrl+单击跳转到reset()函数,函数为mibble中使用的grammatica的 parser类,在web调用时的调试模式下,发现此处打的断点无法到达,而在单个class的main中调试时可到达
test的main:
5、怀疑一下原因:
-
版本冲突
-
包可见性
-
类加载问题
6、进行版本检查,排除版本原因,怀疑是依赖包没下载好,删除本地maven仓库里的依赖,重新下载,结果还是失败。
7、排除包可见性原因。
8、对于类加载问题,使用classloader加载类,正常输出方法名,类加载正常。
9、最后发现是mibble本身引入的包的问题
<dependency>
<groupId>net.percederberg.mibble</groupId>
<artifactId>mibble</artifactId>
<version>2.9.3</version>
</dependency>
mibble这个依赖本身会引入一个grammatica,但是同时mibble.jar本身会自带一个依赖的grammatic的内容,所以导致二者最后在调用的时候有冲突。
只需要在引入mibble的时候排除调grammatica的包就可以。
<dependency>
<groupId>net.percederberg.mibble</groupId>
<artifactId>mibble</artifactId>
<version>2.9.3</version>
<exclusions>
<exclusion>
<groupId>net.percederberg.grammatica</groupId>
<artifactId>grammatica</artifactId>
</exclusion>
</exclusions>
</dependency>
至于为什么直接在idea里直接跑启动类作为web项目运行时不出错,或者直接跑Main函数时不出错,暂时还没去做分析。