NoCassDefFoundError原因分析

因为需要用到了外部jar中的Class,却在使用时遇到了NoClassDefFoundError,不过最终解决了,留下一个笔记供以后参考。 首先分析一下ClassNoDefFoundError异常,平时熟知的是ClassNotFoundException。ClassNotFoundException是找不到类的异常,那NoClassDefFoundError呢?其实也是找不到类,不过两者有着原理性的区别。

ClassNotFoundException

为类在加载时发现的异常,一般是因为要使用的类在ClassLoader中(由ClassLoder.getSystemClassLoader()获得)找不到,一般是依赖未在classpath中造成。

NoClassDefFoundError

此错误继承自 java.lang.LinkageError,是java.lang.Error类的派生类。含义是使用Class时JVM无法正确获得Class的实例数据(定义的方法、父类、接口、字段等成员)。两者区别在于前者在加载类时找不到类,是属于编译时就可能发现的异常。后者是类加载成功后但无法使用。

现实问题

笔者遇到的问题呢就与这两个异常有关。先说明一下是如何使用的吧。 首先由于需要在动态使用一堆jar包中的Class,于是使用URLClassLoader把对应的Jar包全部包含。然后使用这个classLoader动态加载类来使用(使用Reflections查找被某些注解过的类)。 由于Class就存在于diy的ClassLoader的范围,Class加载成功,getCanonicalName()获得类全路径正常。然后继续去读取Class中定义的字段、方法中被部分注解过的进行筛选。就在getDeclaredFields()或getDeclaredMethods()方法被调用时却抛出NoClassDefFoundError。而异常中的类却是这个Class内被引用过的类(暂叫DependencyClass),但DependencyClass在diy的ClassLoader的范围,单独加载也能成功加载。

问题分析

继承查看异常信息,原来是NoClassDefFoundError中又包裹了一层ClassNotFoundException。 观其异常调用堆栈是在使用当前调用类的ClassLoader(sun.reflect.Reflection.getCallerClass()加载的ClassLoader)来加载Class的依赖。但当前调用类的ClassLoader并不存在DependencyClass。

解决

找到原因问题就快解决了,因为是调用类所在ClassLoader找不到依赖的Class,那可以进行几种方式解决:

  1. 在工程的依赖中添加找不到类的依赖,这样做会增加依赖。
  2. 在调用类之前获得系统ClassLoader,将找不到类的jar添加到ClassLoader的依赖中(AppClassLader继承于URLClassLoader可通过反射修改ClassLoader来添加Jar)这种方法的依赖jar只能添加不能删减,可能影响系统稳定性) 具体方法见 https://blog.csdn.net/fd2025/article/details/80538468
  3. 将方法代码写成工具,与diy的ClassLoader中的jar一起加载,通过反射+反射方式实现。

以上内容纯属个人经验,不对之处欢迎来怼。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值