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就會更新配置。太具體的沒有深入瞭解,這裏也歡迎大佬們指點。
日誌終於正常了 ( Ĭ ^ Ĭ ) 完結撒花!