ClassNotFoundException和NoClassDeFoundError
来源:互联网 发布:多目标粒子群算法代码 编辑:程序博客网 时间:2024/05/17 22:02
今天又出现了NoClassDefFoundError这个错误,其实已经出现过很多次了,也知道了一般都是缺少相关Jar包之类的造成的,但是也没进行更深入的了解,今天我们就来稍微的探究一下这个错误到底怎么发生的,他和ClassNotFonudException这一常见异常又有什么区别呢。
我们知道这两个Java类都属于异常,那么我们首先来看看他们是checked exception还是unchecked exception。
我们看看ClassNotFonudException:
ClassNotFonudException->ReflectiveOperationException->Exception
很显然ClassNotFoundException是checkedException。
而NoClassDefFoundError
NoClassDefFoundError->LinkageError->Error
祖先是Error,不用说,是uncheckedException,而且是Error的子孙类,我们知道Error属于JVM等引发的不可挽救的错误,会直接让程序宕了。
我们再看看在Java API文档中是怎么定义他们的
ClassNotFonudException
当应用程序试图使用以下方法通过字符串名加载类时,但是没有找到具有指定名称的类的定义。抛出该异常:
- Class 类中的 forName 方法。
使用Classs.forName来加载类时,会进行初始化的工作,所以如果想仅仅是干干净净的加载类的话,最好还是用ClassLoader中的loadClass。当然如果你是使用
Class<?> forName(String name, boolean initialize, ClassLoader loader)
这个方法,且第二个参数为false时(参数见名知义),也不会进行初始化工作。
- ClassLoader 类中的 findSystemClass 方法。
此方法通过系统类加载器(参见 getSystemClassLoader())来加载该类
protected final Class<?> findSystemClass(String name) throws ClassNotFoundException { ClassLoader system = getSystemClassLoader(); if (system == null) { if (!checkName(name)) throw new ClassNotFoundException(name); Class<?> cls = findBootstrapClass(name); if (cls == null) { throw new ClassNotFoundException(name); } return cls; } return system.loadClass(name); }
getSystemClassLoader:获取系统类加载器的方法,那么什么是系统加载器呢,是Bootstrap这个祖先类加载器吗?不是的,系统类加载器是系统的入口点所使用的ClassLoader。一般是App ClassLoader。
Boootstrap->extsion->app classLoader,这三级类加载器大家应该都清楚作用吧,不清楚的话得好好补补基础啦。
- ClassLoader 类中的 loadClass 方法。
loadClass,很干净的加载类的方法。说到loadClass就有必要说我之前看过的自定义ClassLoader了。我们知道Java字节码文件是很容易被反编译的,我们常见的jd-gui反编译工具,反编译class文件是不是很方便。所以当我们的Java代码有安全性要求的时候,我们可以通过自定义ClassLoader来加密我们的Java代码(虽然一般不会用到)。那么自定义ClassLoader主要需要做些什么呢。我们先看loadClass方法的源码(源码版本均为JDK8)
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
其实如果你仔细看这个类的话,你会发现他给我们传递了很多信息。
- 首先,他告诉了我们ClassLoader的树形结构,从祖先类加载器开始,依次往下查找是否能够加载该类。
- 然后, 我们通读代码,发现,如果没有在JVM中的三个类加载成功加载的话,会执行 c = findClass(name);
这句话很关键,这句代码给了我们重写的空间。
实际上,我们实现我们自己定义的ClassLoader的话,只需要重写这个方法。然后我们需要在这个方法里调用defineClass方法,因为这个方法的作用是把字节码转化为Class对象(类加载的最终产品就是位于堆上的Class对象)。
扯了这么多好像还是没有讲出现这个异常的原因,其实简单来说:
ClassNotFoundException只可能出现在你的应用程序主动的装载类的过程中,可能是使用框架配置的初始化过程中,也有可能是程序中动态调用你认为已经写好的类中,但是很实际情况下,你在尝试调用一个实际上不存在的类,赶紧查一下是名称写错了,还是没有把他配置到正确的配置文件中吧。
扯的有点跑偏,最近喜欢把相关的东西结合在一起讲,搞得很多时候没有重点,很尴尬。好,对于ClassNotFountException的API文档就讲到这里,接下来看NoClassDeFoundError
NoClassDeFoundError
API文档是这样说的:
当 Java 虚拟机或 ClassLoader 实例试图在类的定义中加载(作为通常方法调用的一部分或者作为使用 new 表达式创建的新实例的一部分),但无法找到该类的定义时,抛出此异常。
当前执行的类被编译时,所搜索的类定义存在,但无法再找到该定义。
简单点的理解可以是这样:你如果编译了一个类B,在类A中调用,编译完成以后,你又删除掉B,运行A的时候那么就会出现这个错误(这就是缺少JAR包的情况),还有的情况可能是Classpath路径更改了也会造成这个问题。
- NoClassDefoundError 和 ClassNotFoundException 区别
- ClassNotFoundException和NoClassDeFoundError
- ClassNotFoundException 和 NoClassDefFoundError 区别
- ClassNotFoundException 和 NoClassDefFoundError 区别
- ClassNotFoundException和NoClassDefFoundError区别
- ClassNotFoundException 和 NoClassDefFoundError
- ClassNotFoundException 和 NoClassDefFoundError 区别
- ClassNotFoundException和NoClassDefFoundError
- ClassNotFoundException 和 NoClassDefFoundError 区别
- NoClassDefFoundError和ClassNotFoundException区别
- ClassNotFoundException和 NoClassDefFoundError
- NoClassDefFoundError和ClassNotFoundException区别
- NoClassDefFoundError和ClassNotFoundException问题分析
- ClassNotFoundException和NoClassDefFoundError的区别
- 关于NoClassDefFoundError和ClassNotFoundException异常
- ClassNotFoundException和NoClassDefFoundError的区别
- NoClassDefFoundError 和ClassNotFoundException的区别
- ClassNotFoundException和NoClassDefFoundError的区别
- QOS
- 快速排序的最优和最差比较次数
- Caffe+Ubuntu16.04+cuda8.0安装步骤
- 不一样的C语言-当sizeof遇上数组名
- 不是每个人都要去创业,但应该都要有创业家精
- ClassNotFoundException和NoClassDeFoundError
- [stm32] USART USART1收发功能工程
- [stm32] USART USART1收发功能工程
- SPOJ-MINSUB
- 解析导致的文件上传漏洞
- Windows配置caffe
- Spring MVC源码分析—Servlet解析
- 第一与第二次作业
- what is Agile development ?