閱讀299 返回首頁    go 京東網上商城


《SLF4J官方文檔》SLF4J警告或錯誤信息及其含義

調用方法o.a.commons.logging.impl.SLF4FLogFactory.release

已給出的公用日誌API(common-logging API),實際上是由SLF4J實現的,o.a.commons.logging.impl.SLF4FLogFactory.release方法永遠不會被調用。然而,取決於commons-logging.jar在服務器小程序容器的部署,release()方法可能意外地通過commons-logging.jar裝載的org.apache.commons.logging.LogFactoryl類被調用。

當Tomac安裝後,$TOMAC_HOME代表目錄;在最近的Tomac版本上,這是個普遍的現象,尤其當你在應用中在WEB-INF/lib下放置jcl-over-slf4j.jar而不是在$TOMCAT_HOME/common/lib下放置jar包。為了完全獲得jcl-over-slf4j.jar包的穩定性,我們建議你在$TOMCAT_HOME/common/lib目錄下放置jcl-over-slf4j.jar包,沒有在你的web應用裏放置副本。

也請你看下bug#22

jcl-over-slf4j不支持的[某個]操作

當調用JCL1.1中受保護的方法,會拋出不支持操作異常 (UnsupportedOperationException)。這些方法都是通過commons-logging.jarLogFactory 實現調用。 當然,LogFactory由 jcl-over-slf4j.jar包下的SLF4FLogFactory實現,SLF4FLogFactory不調用這些方法。

如果你研究這個問題,很大可能是你的commons-logging.jar副本在類的路徑下覆蓋了jcl-over-slf4j.jar包中的類。

當調用o.a.commons.logging.impl.SLF4FLogFactory.release()方法時,注意實際上這個問題跟發出的警告是非常相似的,已在前一個章節討論了。

日誌名稱不匹配檢測

隻有slf4j.detectLoggerNameMismatch係統屬性設置為true時,日誌名稱不匹配警告才會打印。默認情況下,這個屬性沒有設置,即使在日誌名稱不匹配的情況下也不會打印警告。

從1.7.9開始,在指定名稱的日誌器下,向LoggerFactory.getLogger(Class)方法傳參,警告信息就會被打印,這個方法和SLF4J內部推斷的調用者的名稱不同。

例如,代碼塊如下:

package com.acme;
import com.foo.Kangaroo;

class <strong>Fruit</strong> {
Logger logger = LoggerFactory.getLogger(Kangaroo.class);
}

結果將會顯示:

SLF4J: Detected logger name mismatch. Given name:

"com.foo.Kangaroo"; computed name: "com.acme.Fruit".

但隻在slf4j.detectLoggerNameMismatch係統屬性設置為true時才顯示。

當日誌器中傳入的參數類是一個基類,這種特定情況下子類不會出現任何警告信息,例如:

class A {
Logger logger = LoggerFactory.getLogger(getClass());
}
class B extends A {
// no mismatch warning will be issued when B is instantiated
// given that class A is a super-type of class B
}

如果你遇到不能解釋的不匹配警告,你可以用白色大象標記它,當定義了日誌器,這種不能正確推斷出類名的情況是非常少的。我們也很有興趣去獲得這些類。如果你標記了一個無法解釋的不匹配信息,請給我們發一個[日誌報告]( https://www.slf4j.org/bug-reporting.html)文件。

加載org.slf4j.impl.StaticLoggerBinder類失敗

當org.slf4j.impl.StaticLoggerBinder類不能從內存中加載是,將會報告這個錯誤信息。當在類路徑中沒有合適的SLF4J綁定時,這種情況會發生。放置一個jar包(隻能放其中的一個):slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar, logback-classic.jar。在類路徑中放置一個就可以解決問題。

從1.6.0: 1.6版本的SLF4J,沒有綁定,SLF4J默認是一個無操作日誌實現。

你可以從項目下載頁(https://www.slf4j.org/download.html)下載SLF4J綁定。

在類路徑下發現多個綁定

SLF4J被設計成依次與每個且隻有一個基本日誌框架綁定。如果在類路徑下存在不止一個綁定。SLF4J將發出一個警告,列出這些綁定的位置。

當多個綁定在類路徑下,隻能選取一個你想用的綁定,移除其他綁定。比如,如果在類路徑下同時有slf4j-simple-1.7.19.jar和 slf4j-nop-1.7.19.jar,你想用無操作綁定,那麼把slf4j-nop-1.7.19.jar從類路徑中移除。

這個SLF4J提供的警告信息位置列表 為識別過渡添加到項目中不想要的SLF4J綁定依賴包 提供了有效的信息。在項目中pom.xml文件中,剔除掉那些隨意聲明的依賴包下的SLF4J綁定。例如,cassandra-all版本0.0.1同時把log4jslf4j-log4j12聲明為編譯時間關聯。由此,當你把cassandra-all作為依賴包包含到你的項目中,cassandra-all聲明將導致log4jslf4j-log4j12同時被添加為依賴包。假使SLF4J在後台時,你不想用log4J,你可以告訴Maven這倆個文件,如下文顯示:

<dependencies>
 <dependency>
  <groupId> org.apache.cassandra</groupId>
  <artifactId>cassandra-all</artifactId>
  <version>0.8.1</version>

  <exclusions>
   <exclusion>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
   </exclusion>
   <exclusion>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
   </exclusion>
  </exclusions>

 </dependency>
</dependencies>

注意:SLF4J發出的警告隻是警告。甚至多個綁定存在時,SLF4J將選取一個日誌框架/實現,然後與它綁定。SLF4J選取綁定的方式由java虛擬機決定,應該隨機考慮所有的實際目的。1.6.6版本,SLF4J會以框架/實現類的實際範圍命名。

例如類庫或框架的這些嵌入的組件不能聲明任何SLF4J的綁定,除了依賴slf4j-api。當一個包庫在SLF4J綁定上聲明一個編譯時間依賴,它會欺騙你並且綁定到最後的用戶,這樣就與 SLF4J的目的背道而馳了。當你遇到嵌入組件在SLF4J綁定上聲明編譯時間依賴,請及時聯係這些作者,友好地請他們修複這些方法。

Slf4j-api版本不匹配綁定

SLF4J綁定標明人工打的jar包,例如用來把slf4j綁定到基本日誌框架的slf4j-jdk14.jar 或 slf4j-log4j12.jar,java.util.logging和個別log4j。

混用不同版本的slf4j-api.jar和SLF4J綁定會導致問題。例如,如果你用slf4j-api-1.7.19.jar,然後你也應該用slf4j-simple-1.7.19.jar,用slf4j-simple-1.5.5.jar將不起作用。

注意: 從客戶端的角度,所有版本的slf4j-api版本都是兼容的。在任意N和M版本slf4j-api下,通過slf4j-api-N.jar編譯的客戶端代碼在slf4j-api-M.jar下也將運行良好。你隻需確定綁定版本匹配slf4j.jar。你不需要擔心項目中已給出的依賴庫slf4j-api的版本。你能用任意slf4j-api.jar版本,隻要slf4j-api.jar版本和它的綁定匹配,就不會有問題。

在初始化時,如果SLF4J懷疑有任任何api和綁定版本不匹配問題,它將發出被疑似不匹配的警告信息。

日誌工廠實現不能為空

這個錯誤在LoggerFactory類找不到合適的綁定時會報告。在類路徑下放置slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar logback-classic.jar中的一個包(隻能放一個),這會是個有效的改正方法。

在類路徑下檢測log4j-over-slf4j.jar和 slf4j-log4j12.jar包,替代堆溢出錯誤

slf4j-log4j12 模塊的目的是把從log4j日誌到SLF4J的調用轉移或重定向。Log4j-over-slf4j模塊的目的是把從Log4j-over-slf4j日誌到SLF4J的日誌記錄重定向。如果SLF4J屬於slf4j-log4j12.jar和slf4j-log4j-over-slf4.jar,也會在出現在類路徑中,堆溢出錯誤必然會在第一次調用SLF4J或log4j日誌時出現。

如下是類似的異常:

Exception in thread "main" java.lang.StackOverflowError
at java.util.Hashtable.containsKey(Hashtable.java:306)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:36)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.log4j.Category.<init>(Category.java:53)
at org.apache.log4j.Logger..<init>(Logger.java:35)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.log4j.Category..<init>(Category.java:53)
at org.apache.log4j.Logger..<init>(Logger.java:35)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
subsequent lines omitted...

SINCE 1.5.11  SLF4j取代了必然發生的堆溢出錯誤,通過拋出一個關於問題實際情況的詳情的異常。這比讓用戶去想堆溢出錯誤的原因要好多了。

更多其他關於這個主題的更多背景,查看Bridging legacy APIs(https://www.slf4j.org/legacy.html)。

在類路徑下檢測jcl-over-slf4j.jar 和 slf4j-jcl.jar包,替代堆溢出錯誤

slf4j-jcl模塊的目的是把從SLF4J到JCL(jakarta commons logging)的調用轉移或重定向。jcl-over-slf4j模塊的目的是從JCL日誌到SLF4J的日誌記錄轉移或重定向。如果SLF4J屬於jcl-over-slf4j.jar和slf4j-jcl.jar,也會在出現在類路徑中,堆溢出錯誤必然會立即在第一次調用SLF4J或JCL日誌時出現。

如下是類似的異常:

Exception in thread "main" java.lang.StackOverflowError
at java.lang.String.hashCode(String.java:1482)
at java.util.HashMap.get(HashMap.java:300)
at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:67)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:289)
at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:69)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
subsequent lines omitted...

從版本 1.5.11開始  SLF4j取代了必然發生的堆溢出錯誤,通過拋出一個關於問題實際情況的詳情的異常。這比讓用戶去想堆溢出錯誤的原因要好多了。

更多其他關於這個主題的更多背景,查看Bridging legacy APIs

加載類” org.slf4j.impl.StaticMDCBinder”失敗

這個錯誤表明在類路徑下沒找到合適的SLF4J綁定。在類路徑下放置slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar logback-classic.jar中的一個包(隻能放一個)會解決這個問題。

MDCAdapter不能為空

當org.slf4j.MDC class類沒有被正確地初始化時會報告此錯誤。像上麵已列出的項一樣的情況和改正方案。

 

在初始化階段攔截一定數量(N)的日誌記錄,現在重新顯示。這些遵循底層日誌係統過濾規則

從1.7.版本,在初始化階段產生的日誌記錄被記錄下來,然後在初始化完成後重新顯示。注意重新顯示的日誌記錄遵循底層日誌係統過濾規則。

原則上,應用中重新顯示出現在第一次日誌記錄發生時,這時多線程已經啟動。

查看substitute loggers

在底層日誌係統的默認配置階段創建替代日誌器

像logback和log4j這樣的高級可配置日誌係統,它們會在自身初始化過程中創建可調用日誌器的組件。查看典型的事件LOGBACK-127(https://jira.qos.ch/browse/LOGBACK-127),它不可能實現這樣的日誌創建請求。

為了避免這種雞和蛋問題,在這個過程中(初始化),SLF4J創建了替代日誌器。在此階段替代日誌器的記錄被簡單地扔掉了。在初始化完成後,替代日誌器將轉移記錄早合適的日誌器實現,不然將會作用在LogFactory返回的日誌器上。

如果已創建任何替代日誌器,SLF4J將發出一個日誌的列表。這個列表意欲讓你知道在初始化過程中被這些日誌器拋棄的任何日誌記錄。

查看intercepted and replayed logging calls

SLF4J 1.4.0版本,需要1.2.12及以上的版本

在2005.8.29發布的log4j1.2.12版本增加了跟蹤等級。在2007.5.16的SLF4J API中增加了跟蹤等級。這樣,,啟動SLF4J1.4.0時,綁定給SLF4J的log4j需要log4j1.2.12及其以上的版本。

當然,像在文件59報告的一樣(https://jira.qos.ch/browse/SLF4J-59),在你某些環境下,這可能會很難升級log4j版本。為了解決這樣的情況,SLF4J的Log4jLOggerAdapter將把跟蹤等級指為調試級別。

 

java.lang.NoClassDefFoundError: org/slf4j/event/LoggingEvent

Logback-classic version 1.1.4及其以後的版本需要1.7.15及其以上版本的slf4j-api。

類路徑中的早期slf4j-api.jar,1.1.4及其以後的logback版本返回的試圖內省的日誌實例將導致類似於下麵顯示的NoClassDefFoundError。

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/event/LoggingEvent
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2451)
at java.lang.Class.privateGetPublicMethods(Class.java:2571)
at java.lang.Class.getMethods(Class.java:1429)
at java.beans.Introspector.getPublicDeclaredMethods(Introspector.java:1261)
at java.beans.Introspector.getTargetMethodInfo(Introspector.java:1122)
at java.beans.Introspector.getBeanInfo(Introspector.java:414)
at java.beans.Introspector.getBeanInfo(Introspector.java:161)

在類路徑下放置1.7.15及其以上的slf4j-api.jar包可以解決此問題。

記住這個問題隻會出現在1.1.4及其以後的logback版本,其他的綁定,例如slf4j-log4j, slf4j-jdk14 and slf4j-simple是不受影響的。

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 17:01:56

  上一篇:go  《Spark 官方文檔》在YARN上運行Spark
  下一篇:go  Java網絡編程:UDP DatagramSocket