NoClassDefFoundError的两种情况
ClassNotFoundException vs. NoClassDefFoundError
ClassNotFoundException
关于ClassNotFoundException发生的原因,这篇文章ClassNotFoundException vs. NoClassDefFoundError写得很清晰。
总的来说就是:
- 需要加载的类在classpath中找不到,一般这种情况都是使用类似
Class.forName("oracle.jdbc.driver.OracleDriver")
的方式获取类不存在
解决问题的思路:
- 排查导入的jar包,对于使用maven的程序来说,就是去检查pom.xml中的配置
- 如果配置的有的话就去看一下maven实际导入的jar包中,对应路径下是否有这个类
NoClassDefFoundError
关于ClassNotFoundException发生的原因,这篇文章ClassNotFoundException vs. NoClassDefFoundError写得很清晰。
总的来说就是:
- 这个类编译时有,但是运行时没有
解决问题的思路:
- 缩小范围,确定是哪个类的definition找不到。确定原因后再定解决办法
以下我演示两个NoClassDefFoundError的情景。
NoClassDefFoundError的情景
情景1.
B项目依赖了A项目,并配置<optional>
为true。
<dependency>
<groupId>com.example</groupId>
<artifactId>a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
C项目依赖了B项目,并调用B项目中的某个方法,该方法调用了A项目的代码。
此时会发生NoClassDefFoundError
报错。
情景2.
- B项目依赖了A项目
- C项目依赖了B项目
- C项目也依赖了A项目
C项目调用B项目中的某个方法,该方法调用了A项目xxx类的代码。
正常来说这个过程是没问题的,但是B项目、C项目使用的A项目版本不同。
A项目xxx类在这两个版本的包路径不同。
这个是我用hutool的过程中发现的一个问题,NetUtil在项目不同版本中包位置不一样。
Note.
需要注意的一点是,如上两个情景,虽然都是因为少了A项目的代码,所以一般堆栈信息会直接报错是找不到A项目某个类的definition。
但如果使用A项目的代码是在B项目的static块中(<cinit>
方法执行失败),那么此时会报的是找不到B项目这个类的definition。