bug之旅1.1:ClassNotFoundException和NoClassDefFoundError 傻傻分不清楚

一次网关服务日志升级引起的反思

背景

web端服务,程序执行日志写入动作时(如log.info、log.error),不能执行后续代码,必须等待日志行代码执行完毕,才能继续执行后续的代码,影响了执行速度。为了提升web端服务性能,整个网关服务启用log4j2的异步日志功能。日志的写入和日志文件的产生通过后台守护线程来完成。

动作

原来的
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger=LoggerFactory.getLogger(this.getClass);
改为
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static final Logger logger=LoggerFactory.getLogger(XXX.class);

同时注释掉pom中slf4j相关的依赖。

现象

前置条件,后台服务启动(以下的几次接口调用期间,是在同一次服务启动后调用的。服务没有多次重启,此为伏笔)
第一次调用接口API-A:(p1.1.1)
p1.1.1第二次、第三次调用API-A:,(p1.1.2)
p1.1.2

分析

动作 中已经指出 注释掉pom中slf4j相关的依赖。因此抛出ClassNotFoundException异常,是正常的。原因看下图p1.1.3、p1.1.4
p1.1.3p1.1.4因为ldsf.jar包中依赖slf4j相关的包,而slf4j被注释掉了。
那么,为什么后续会一直出现NoClassDefFoundError错误?
服务启动,类加载后,当调用接口时,第一次调用Json2Util类,给静态变量Logger赋值,触发Json2Util的初始化,由于没有Slf4j相关的jar包,因此在
private static final Logger logger=LoggerFactory.getLogger(this.getClass);时抛出ClassNotFoundException异常,初始化失败。此时Json2Util的初始化状态是失败,并且把此状态保存在缓存中。接口第二次调用时,检测到缓存中Json2Util已经初始化,不再执行初始化代码(因此不会再出现ClassNotFoundException异常)。检查Json2Util的初始化状态(是否可用,是否定义成功),发现此类初始化失败,不可用,直接抛出NoClassDefFoundError错误。第三次、第四次…均抛出NoClassDefFoundError错误,因为类只初始化一次。(伏笔中提到,多次调用接口期间服务并未重启,原因正在此处。)

总结

同一个类被调用两次,第一次抛出ClassNotFoundException异常,以后的每次都抛出NoClassDefFoundError错误。是因为类加载机制的底层实现造成的。由于对jvm底层不熟悉,因此,这部分暂时没有能力配图详细分析,待以后慢慢提升和补充。

疑问

为什么在maven项目编译打包时,没有检测出ClassNotFoundException异常?请技术大牛们多多指点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值