ClassNotFoundException和NoClassDefFoundError的区别

简介: ClassNotFoundException和NoClassDefFoundError的区别

最近看到一个面试题,问ClassNotFoundException和NoClassDefFoundError的区别。平时没有专门思考过这个问题,藉此机会分析一下。

一个直观的区别是一个是异常,一个是错误,异常和错误的区别就可以先讲一波。

然后其他的相同点和不同点在看到的一篇非常好的英文文章中有详细的讲述,翻译在此。

1. 介绍

ClassNotFoundExceptionNoClassDefFoundError都发生在JVM在classpath下找不到所需的类时。

虽然看起来很相似,但是两者有很大不同。

本文我们将介绍他们是怎样出现的以及怎么去解决这些错误。

2. ClassNotFoundException

当应用尝试在类路径中用全限量名去加载某个类时,如果找你不到它的定义就会报CLassNotFoundException 。它是一个可检测异常。

通常出现在用Class.forName(), ClassLoader.loadClass()ClassLoader.findSystemClass()这三个方法加载类的时候我们在使用反射的时候,要特别注意这个异常。

下面这个例子,我们尝试加载的JDBC驱动没有添加到类路径中(没有添加依赖),将会报ClassNotFoundException。

1. @Test(expected = ClassNotFoundException.class)
2. public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException()
3. throws ClassNotFoundException {
4.       Class.forName("oracle.jdbc.driver.OracleDriver");
5. }

 

3. NoClassDefFoundError

NoClassDefFoundError是一种致命错误。

当JVM尝试通过new关键字创建一个类实例或者方法调用来加载一个类时找不到这个类的定义就会出现这个错误。

通常是编译时正常编译,但是运行时找不到这个类。

通常发生在执行动态代码块或者初始化静态字段时报了异常,从而导致类初始化失败而引发NoClassDefFoundError。

1. public class ClassWithInitErrors {
2. static int data = 1 / 0;
3. }
1. public class NoClassDefFoundErrorExample {
2. public ClassWithInitErrors getClassWithInitErrors() {
3.         ClassWithInitErrors test;
4. try {
5.             test = new ClassWithInitErrors();
6.         } catch (Throwable t) {
7.             System.out.println(t);
8.         }
9.         test = new ClassWithInitErrors();
10. return test;
11.     }
12. }

编写测试用例

1. @Test(expected = NoClassDefFoundError.class)
2. public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() {
3. 
4. NoClassDefFoundErrorExample sample
5. = new NoClassDefFoundErrorExample();
6.     sample.getClassWithInitErrors();
7. }

4. 解决办法

排查和修复这两个问题有时候会非常耗时。

他们的主要原因是运行时类路径中类文件不可用。

下面是几点具体的原因:

  1. 排查所需的jar包是否在类路径中,如果没有就添加进去。
  2. 如果发现类在classpath里面,很有可能是classpath被重写了,需要再次确定应用准确的classpath
  3. 依赖包发生了冲突,比如应该依赖高版本jar包,但又其它包传递依赖了低版本jar包,导致高版本中某些类找不到。
  4. 如果应用中用到了多个类加载器,一个类加载器加载的类,无法再其他的类加载器中使用。

5、总结

ClassNotFoundException与NoClassDefException核心区别是,前者强调运行时无法匹配到指定参数名称的类,后者强调编译时没问题,运行时却无法实例化一个类

最常见的解决方法是检查是否依赖了相关包或者相关包是否有冲突

 

英文原文:https://www.baeldung.com/java-classnotfoundexception-and-noclassdeffounderror

源代码地址:https://github.com/eugenp/tutorials/tree/master/core-java-lang

 

相关文章
|
存储 NoSQL 算法
【Redis】过期淘汰策略以及内存淘汰机制
【Redis】过期淘汰策略以及内存淘汰机制
474 0
【Redis】过期淘汰策略以及内存淘汰机制
|
监控 Cloud Native 数据库
【阿里云云原生专栏】性能优化之道:阿里云云原生平台上的监控与调优策略
【5月更文挑战第22天】本文介绍了阿里云云原生平台的监控与调优策略。阿里云提供如CloudMonitor、ARMS和ACK监控等工具,用于基础和应用监控,以及容器监控。调优策略包括资源、代码和架构优化,例如根据监控数据调整资源配置,优化代码性能,和利用微服务、容器化和无服务器化改进架构。示例代码展示了如何进行监控和调优操作,强调实时监控与针对性调优对提升云原生应用性能的重要性。
570 1
|
12月前
|
自动驾驶 物联网 5G
5G网络的演进:从理论到实践
【10月更文挑战第3天】5G网络作为新一代移动通信技术,不仅在理论上实现了重大突破,而且在实践中也展现出了强大的生命力。本文将围绕5G网络的演进,从理论基础到实际应用,探讨5G技术的发展和实践案例,同时提供代码示例以供参考。
523 6
|
JSON Java fastjson
java小工具util系列3:JSON和实体类转换工具
java小工具util系列3:JSON和实体类转换工具
223 2
|
12月前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
199 0
|
存储 缓存 NoSQL
Redis深度解析:部署模式、数据类型、存储模型与实战问题解决
Redis深度解析:部署模式、数据类型、存储模型与实战问题解决
|
机器学习/深度学习 数据采集 数据可视化
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
|
存储 前端开发 Java
深入剖析ThreadLocal使用场景、实现原理、设计思想
深入剖析ThreadLocal使用场景、实现原理、设计思想
深入剖析ThreadLocal使用场景、实现原理、设计思想
|
存储 资源调度 Kubernetes
新书自荐《深入集群:大型数据中心资源调度与管理》
深入集群 大型数据中心资源调度与管理,已经第2版了(2021-10月)。之前在ata和百晓生发布了新书自荐,这次同步到社区。
899 1
新书自荐《深入集群:大型数据中心资源调度与管理》
|
存储 Kubernetes 物联网
K3S完美部署
K3S完美部署
1275 3