由于须要用到了外部jar中的Class,却在使用时遇到了NoClassDefFoundError,不过最终解决了,留下一个笔记供之后参考。 首先分析一下ClassNoDefFoundError异常,平时熟知的是ClassNotFoundException。ClassNotFoundException是找不到类的异常,那NoClassDefFoundError呢?其实也是找不到类,不过二者有着原理性的区别。java
为类在加载时发现的异常,通常是由于要使用的类在ClassLoader中(由ClassLoder.getSystemClassLoader()得到)找不到,通常是依赖未在classpath中形成。工具
此错误继承自 java.lang.LinkageError,是java.lang.Error类的派生类。含义是使用Class时JVM没法正确得到Class的实例数据(定义的方法、父类、接口、字段等成员)。二者区别在于前者在加载类时找不到类,是属于编译时就可能发现的异常。后者是类加载成功后但没法使用。spa
笔者遇到的问题呢就与这两个异常有关。先说明一下是如何使用的吧。 首先因为须要在动态使用一堆jar包中的Class,因而使用URLClassLoader把对应的Jar包所有包含。而后使用这个classLoader动态加载类来使用(使用Reflections查找被某些注解过的类)。 因为Class就存在于diy的ClassLoader的范围,Class加载成功,getCanonicalName()得到类全路径正常。而后继续去读取Class中定义的字段、方法中被部分注解过的进行筛选。就在getDeclaredFields()或getDeclaredMethods()方法被调用时却抛出NoClassDefFoundError。而异常中的类倒是这个Class内被引用过的类(暂叫DependencyClass),但DependencyClass在diy的ClassLoader的范围,单独加载也能成功加载。.net
继承查看异常信息,原来是NoClassDefFoundError中又包裹了一层ClassNotFoundException。 观其异常调用堆栈是在使用当前调用类的ClassLoader(sun.reflect.Reflection.getCallerClass()加载的ClassLoader)来加载Class的依赖。但当前调用类的ClassLoader并不存在DependencyClass。blog
找到缘由问题就快解决了,由于是调用类所在ClassLoader找不到依赖的Class,那能够进行几种方式解决:继承
以上内容纯属我的经验,不对之处欢迎来怼。接口