Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar 解决方法
问题:
导入spark依赖包后,local模式下运行spark本地程序报错:
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path,
preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
这个错运行spark程序比较常见,由于很多maven项目中都依赖了log4j的包,这里需要针对冲突的包执行exclude即可
第一层(exclusion 报错jar 包的log4j即可):
网上最常见的解决方法,也是报错日志官方给出的解决方案
假设我加入了spark core的依赖包:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.2.1</version>
</dependency>
增加exclusion去掉上述依赖冲突的包
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.2.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
第二层(org.4j版本不一致问题):
这里需要查看maven依赖树,找到高版本,手动添加到依赖中 https://mvnrepository.com/artifact/log4j/log4j
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.x.x</version>
</dependency>
根据maven树的最高版本手动加入pom即可,maven树获取可以参考上一篇博文~
第三层(报错在底层代码库):
第一层的情况是显示的,即抛出的异常中包含了jar冲突的maven依赖,直接去除即可。但也有一些底层的jar包,我遇到的情况是hadoop client 和 hadoop mapreduce库中的log4j冲突,而hadoop包并不是我自己pom引入,这个时候需要自己引入hadoop client包并exclusion掉log包
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
第四层(很坑):
经历前三种情况之一后,发现我本地的log显示有问题,虽然spark程序运行正常,但是新增了很多spark底层日志,怀疑是自己exclusion掉log4j的原因。
首先想到的就是通过设置spark level级别,彻底去除spark日志
Logger.getLogger("org").setLevel(Level.OFF)
本来以为问题搞定,结果又报错:
value setLevel is not a member of org.apache,log4j.logger
这里提示没有setLevel函数的api接口,但是正常是不会出现这个状况,所以应该是自己exclusion过程或者版本升级过程中出现问题。
解决方法:
将log4j/properties文件放入resource中执行maven install,上述函数setLevel方法恢复正常,日志系统显示正常。
这里简单查了下应该是不配置的情况下会默认读取spark core依赖中的log4.properties.samples,当我在项目resource中覆盖后,log4j就会更新配置。太具体的没有深入了解,这里也欢迎大佬们指点。
日志终于正常了 ( Ĭ ^ Ĭ ) 完结撒花!
来源:oschina
链接:https://my.oschina.net/u/4333379/blog/4305993