首先了解下 ClassNotFoundException 和 NoClassDefFoundError 的区别
ClassNotFoundException
JVM 启动前会检查所有必要的 class 资源是否存在
如果发现有 class 资源缺失
报此异常
JVM 启动失败
NoClassDefFoundError
JVM 启动前会检查所有必要的 class 资源是否存在
但并不会立即加载那些未使用的客户 class
而是选择需要时再加载
JVM 启动成功
如果 JVM 在启动成功后某一时间发现需要加载某个客户 class
而此客户 class 缺失
或此客户 class 存在
但由于 IO 或网络原因造成加载失败
先报 IO 或网络异常
接着报 ClassNotFoundException 异常
再报此异常
对于其它未依赖此客户 class 代码
JVM 仍能正常运行
引发此问题的原因:
所需 class 文件在 JVM 启动前后全部存在,且JVM 启动成功,但 JVM 启动后某个时刻一些未加载的文件不存在,但要加载时即报 NoClassDefFoundError
变量:0 < D < L
场景一:
比如客户端类 c
第一次使用该类的时间为 L 时间(L>0)
但在第 D 时间(D<L)
c 类的 class 文件被删除了
此时时间变为 L
即会报 NoClassDefFoundError
场景二:
比如客户端类 c
第一次使用该类的时间为 L 时间(L>0)
但在第 D 时间(D<L)
(Linux)系统的当前 java 应用 Open Files 达到上限
此时时间变为 L
即会无法打开 c 类的 class 文件
但实际是存在 c 类的 class 文件
依次报 FileNotFoundException -> ClassNotFoundException -> NoClassDefFoundError
造成 Open Files 达到上限的原因有
当前 java 应用可能有大量的系统 IO 操作未 close
或当前 java 应用存在大量的网络连接未 close
ClassNotFoundException
JVM 启动前会检查所有必要的 class 资源是否存在
如果发现有 class 资源缺失
报此异常
JVM 启动失败
NoClassDefFoundError
JVM 启动前会检查所有必要的 class 资源是否存在
但并不会立即加载那些未使用的客户 class
而是选择需要时再加载
JVM 启动成功
如果 JVM 在启动成功后某一时间发现需要加载某个客户 class
而此客户 class 缺失
或此客户 class 存在
但由于 IO 或网络原因造成加载失败
先报 IO 或网络异常
接着报 ClassNotFoundException 异常
再报此异常
对于其它未依赖此客户 class 代码
JVM 仍能正常运行
引发此问题的原因:
所需 class 文件在 JVM 启动前后全部存在,且JVM 启动成功,但 JVM 启动后某个时刻一些未加载的文件不存在,但要加载时即报 NoClassDefFoundError
变量:0 < D < L
场景一:
比如客户端类 c
第一次使用该类的时间为 L 时间(L>0)
但在第 D 时间(D<L)
c 类的 class 文件被删除了
此时时间变为 L
即会报 NoClassDefFoundError
场景二:
比如客户端类 c
第一次使用该类的时间为 L 时间(L>0)
但在第 D 时间(D<L)
(Linux)系统的当前 java 应用 Open Files 达到上限
此时时间变为 L
即会无法打开 c 类的 class 文件
但实际是存在 c 类的 class 文件
依次报 FileNotFoundException -> ClassNotFoundException -> NoClassDefFoundError
造成 Open Files 达到上限的原因有
当前 java 应用可能有大量的系统 IO 操作未 close
或当前 java 应用存在大量的网络连接未 close