2018年3月21日 星期三

Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path

前言

最近在 Gradle 載入 Gretty Plugin,讓 Project 自帶 Container,但遇到了 dependency conflicts ,錯誤訊息如下
caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
        at org.slf4j.impl.Log4jLoggerFactory.(Log4jLoggerFactory.java:54)
        ... 37 more
gradle dep 看了一下,發現 Project 本身使用了 slf4j-log4j12,而 Gretty Run Tomcat Container 時需要依賴 log4j-over-slf4j,就是這兩個 library 造成 conflicts。

為什麼

先來看看 slf4j 官網的兩張圖
  • slf4j-log4j12:application 使用的是 slf4j 介面,再透過 adaptation layer 轉由呼叫 log4j framework。
  • log4j-over-slf4j:aplication 使用的是 log4j framework,但可以透過引入這個 library 取代,將原本使用 log4j API 的呼叫轉換至 slf4j 的介面,然後一樣透過 adaptation layer 轉由呼叫除了 log4j 以外的其他 log framework。
這裡有一個唯一的限制,就是不能橋接到相同的 log framework,為了防止 A-to-B.jar 跟 B-to-A.jar 同時出現在 classpath,而導致 A 與 B 一直不停地互相遞迴呼叫,直到發生 StackOverflowError。
SINCE 1.5.11 SLF4J software preempts the inevitable stack overflow error by throwing an exception with details about the actual cause of the problem. This is deemed to be better than leaving the user wondering about the reasons of the StackOverflowError.
…Detail

解法

就像上面解說的,不要讓 classpath 同時出現 log4j-over-slf4j.jar 跟 slf4j-log4j12.jar 就好囉,哈哈,有講跟沒講一樣~XD
好啦,以我自己上面的案例,因為 Gretty Run Tomcat Container 依賴 log4j-over-slf4j,這我沒辦法改,所以要嘛不要使用 Gretty 或改用 Gretty Jetty Container,要嘛改掉自己 Project,俗話說,改變不了環境,只好改變自己適應環境(疑..
解法一:不使用 slf4j-log4j12.jar 改為直接使用 log4j
解法二:使用 providedRuntime。
providedRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.21'

沒有留言:

張貼留言