java.lang.NoClassDefFoundError: Could not initialize class

今天线上环境发现storm任务日志里有如下异常:
java.lang.NoClassDefFoundError: Could not initialize class... 某依赖工程X一个工具类方法
堆栈信息里找到某dubbo服务A的某方法具体某行抛出的,查看服务A的日志,也有该异常信息。

在服务A的工程里找到那行代码,是在某个计算分支里,的确调用了工程X的一个工具类方法。
有些奇怪,因为这个工具类方法调用已上线运行很久了,以前都没发现这个异常。
注意到该计算分支,判断了某配置中心项的配置,仅配置了该参数的业务才会进该逻辑,查看日志发现,果然是该参数的业务才有此异常。

打开工程X的工具类方法,该工具类没有构造函数,即使用默认的。
注意类前面有一个static Logger定义,private static Logger LOGGER = LogFactory.getLogger(XXX.class),该Logger是项目基础组件封装的,不是slf4j、common-logging等第三方包里的类;
因为static变量在类初始化时先加载,结合异常信息,那么很有可能就是这个static变量初始化失败了。

查看git提交记录,想起两周前有同学改动过,对几个记录日志的方法内部增加了些逻辑,主要是增加记录的字段,同时为了记录catch中的异常,增加了这个Logger。
改动后一周左右,工程X有改动并上线。

工程X是个common包,被各个dubbo工程引用。
查看工程X的依赖,发现如下依赖顺序,X->Y->Z->Logger组件。
查看服务A工程的依赖,依赖A->X并排除了Y,而A并没有直接依赖Logger组件。

那么问题找到了,原因是服务A缺少Logger基础组件依赖,但调用工程X工具类的static变量用到Logger基础组件中的类。
解决方法想到两种:
1.修改工程X该工具类,基础组件的Logger改为用slf4j或common-logging等第三方的Logger;

2.工程X增加Logger组件的依赖。

这里想吐槽下公司的依赖管理,可以说非常混乱了:
基础组件依赖了大量第三方组件,依赖配置的顺序较混乱,有些依赖完全没用上;
业务dubbo工程的依赖也较混乱,各种依赖exclude,并且配置顺序较混乱。
想改变很困难,几年下来的工程,明显没有代码review,估计领导也不重视,
基础代码中的很多作者都不在公司了,2011、2012年的创建时间... 后来接锅者表示╮(╯▽╰)╭

其实第1种方法要好一些,基础组件不应该有大量依赖,但是很多其他工程在引用,改依赖风险较大;
再考虑到工程X未来可能需要基础组件的Logger依赖,选择了第2种方式。


总结:

遇到该异常,除了检查异常信息中的类在依赖中是否存在,很大可能就是类里某static变量或static代码块,它的相关依赖类可能不存在。

猜你喜欢

转载自www.cnblogs.com/cdfive2018/p/10241714.html