排除log4j依赖导致的一个java.lang.NoClassDefFoundError问题

2,470 阅读1分钟

背景

由于前段时间出现的 log4j2 的漏洞,项目中默认用的是logback日志组件,所以想着在 pom.xml 中排除掉了 log4j2 的相关依赖应该影响不大。

现象

在日志文件中有看到有许多这样的错误日志:

java.lang.NoClassDefFoundError: Could not initialize class org.elasticsearch.search.builder.SearchSourceBuilder
    at org.elasticsearch.action.search.SearchRequest.<init>(SearchRequest.java:122)
    at org.springframework.data.elasticsearch.core.RequestFactory.prepareSearchRequest(RequestFactory.java:1098)
    at org.springframework.data.elasticsearch.core.RequestFactory.searchRequest(RequestFactory.java:1061)
    at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.searchScrollStart(ElasticsearchRestTemplate.java:268)

一开始以为是没有这个 SearchSourceBuilder 类,就去代码里查找,发现这个类其实存在的。最后发现服务启动后第一次报了一个这样的错误:

java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager
   at org.elasticsearch.search.builder.SearchSourceBuilder.<clinit>(SearchSourceBuilder.java:84)
   at org.elasticsearch.action.search.SearchRequest.<init>(SearchRequest.java:122)
   at org.springframework.data.elasticsearch.core.RequestFactory.prepareSearchRequest(RequestFactory.java:1098)
   at org.springframework.data.elasticsearch.core.RequestFactory.searchRequest(RequestFactory.java:1061)
   at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.searchScrollStart(ElasticsearchRestTemplate.java:268)

结论

根据服务启动的报第一次这个java.lang.NoClassDefFoundError可知,jvm本来是要加载 SearchSourceBuilder 这个类,这个类初始化时却依赖了 log4j 的 API,而 log4j 的依赖包被我们去掉了,导致最后类 SearchSourceBuilder 一直无法初始化。

其实最后我想表达的是:

  1. java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager 是虚拟机找不到这个类。
  2. java.lang.NoClassDefFoundError: Could not initialize class org.elasticsearch.search.builder.SearchSourceBuilder 则表示这个类无法初始化,而非虚拟机找不到这个类。

解决方案

重新依赖log4j2包并升级至最新版本。