NoClassDefFoundError的两种情况

时间:2023-01-12 13:06:00

ClassNotFoundException vs. NoClassDefFoundError

ClassNotFoundException

关于ClassNotFoundException发生的原因,这篇文章ClassNotFoundException vs. NoClassDefFoundError写得很清晰。

NoClassDefFoundError的两种情况

总的来说就是:

  • 需要加载的类在classpath中找不到,一般这种情况都是使用类似Class.forName("oracle.jdbc.driver.OracleDriver")的方式获取类不存在

解决问题的思路:

  • 排查导入的jar包,对于使用maven的程序来说,就是去检查pom.xml中的配置
  • 如果配置的有的话就去看一下maven实际导入的jar包中,对应路径下是否有这个类
NoClassDefFoundError的两种情况

NoClassDefFoundError

关于ClassNotFoundException发生的原因,这篇文章ClassNotFoundException vs. NoClassDefFoundError写得很清晰。

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在项目不同版本中包位置不一样。
NoClassDefFoundError的两种情况

Note.
需要注意的一点是,如上两个情景,虽然都是因为少了A项目的代码,所以一般堆栈信息会直接报错是找不到A项目某个类的definition。
但如果使用A项目的代码是在B项目的static块中(<cinit>方法执行失败),那么此时会报的是找不到B项目这个类的definition。