Java日志體系日志門面(Slf4j)日志實(shí)現(xiàn)(Log4j狗准、Log4j2)詳解

1克锣、背景

近日發(fā)生兩次因日志使用不當(dāng)導(dǎo)致的線上問題:
1、應(yīng)用明明配置了info日志級(jí)別腔长,卻打印大量的debug日志袭祟,導(dǎo)致磁盤IO較高,很快就報(bào)磁盤空間不足告警

2捞附、應(yīng)用服務(wù)啟動(dòng)后報(bào)StackOverflowError錯(cuò)誤巾乳,無法正常提供服務(wù)

這兩個(gè)問題的本質(zhì)其實(shí)都是Java的日志體系較為龐雜、混亂且使用方式多變導(dǎo)致故俐,如果能對(duì)Java的日志體系有一個(gè)全面的了解想鹰,那這兩個(gè)問題也就比較容易解決了紊婉。

下面我?guī)е蠹依砬妪嬰s的Java日志體系药版,本文意在幫大家梳理Java各日志框架的作用,以及常見日志框架的組合使用喻犁,不會(huì)講解各日志實(shí)現(xiàn)的具體配置槽片,如想了解各日志實(shí)現(xiàn)的配置請(qǐng)前往各日志實(shí)現(xiàn)官網(wǎng)查閱。

2肢础、Java日志框架介紹

使用過Java的同學(xué)應(yīng)該都聽說過Log4j还栓、Slf4j、Log4j2传轰、Logback剩盒、commons-logging等日志框架,了解的多一些的同學(xué)應(yīng)該還會(huì)聽說過日志門面慨蛙、日志實(shí)現(xiàn)等概念辽聊,有的同學(xué)可能就有疑問了纪挎,為什么Java的日志框架這么多?日志門面、日志實(shí)現(xiàn)又是什么跟匆?他們之間又有什么關(guān)系呢异袄?下面我通過這幾個(gè)問題來給大家介紹一個(gè)Java龐雜的日志體系。

1玛臂、日志門面烤蜕、日志實(shí)現(xiàn)是什么?

計(jì)算機(jī)程序設(shè)計(jì)中有一句至理名言:沒有什么是抽象一層不能解決的迹冤,如果有那就再抽象一層讽营。

日志門面就是這樣的一個(gè)存在,由于日志實(shí)現(xiàn)太多了泡徙,所以導(dǎo)致應(yīng)用依賴于具體的日志實(shí)現(xiàn)斑匪,而很多的第三方包引用的日志實(shí)現(xiàn)不同,最終導(dǎo)致應(yīng)用的引用日志實(shí)現(xiàn)混亂不堪锋勺,甚至影響整個(gè)應(yīng)用的正常使用蚀瘸,這時(shí)候JCL和Slf4j就站出來了,他們的原理是抽象一層高層API庶橱,應(yīng)用無需具體的日志實(shí)現(xiàn)贮勃,應(yīng)用只需要依賴API,具體的實(shí)現(xiàn)使用SPI的方式實(shí)現(xiàn)苏章。

日志實(shí)現(xiàn)就是具體的日志功能的實(shí)現(xiàn)了寂嘉,勤勤懇懇的、一絲不茍的打印應(yīng)用中的各種日志的實(shí)現(xiàn)枫绅。

2泉孩、Java日志體系都包含哪些日志框架?

上文我們將日志框架的作用分為了兩類并淋,分別是日志實(shí)現(xiàn)和日志門面寓搬,下面我們將這些常見的日志框架對(duì)號(hào)入座,如下圖所示:


在這里插入圖片描述
  • 1996年早期县耽,歐洲安全電子市場(chǎng)項(xiàng)目組決定編寫它自己的程序跟蹤API(Tracing API)句喷。經(jīng)過不斷的完善,這個(gè)API終于成為一個(gè)十分受歡迎的Java日志軟件包兔毙,即Log4j(由Ceki創(chuàng)建)唾琼。
  • 后來Log4j成為Apache基金會(huì)項(xiàng)目中的一員,Ceki也加入Apache組織。后來Log4j近乎成了Java社區(qū)的日志標(biāo)準(zhǔn)澎剥。據(jù)說Apache基金會(huì)還曾經(jīng)建議Sun引入Log4j到Java的標(biāo)準(zhǔn)庫中锡溯,但Sun拒絕了。
  • 2002年Java1.4發(fā)布,Sun推出了自己的日志庫JUL(Java Util Logging)祭饭,其實(shí)現(xiàn)基本模仿了Log4j的實(shí)現(xiàn)涌乳。在JUL出來以前,Log4j就已經(jīng)成為一項(xiàng)成熟的技術(shù)甜癞,使得Log4j在選擇上占據(jù)了一定的優(yōu)勢(shì)夕晓。
  • 接著,Apache推出了Jakarta Commons Logging悠咱,JCL只是定義了一套日志接口(其內(nèi)部也提供一個(gè)Simple Log的簡(jiǎn)單實(shí)現(xiàn))蒸辆,支持運(yùn)行時(shí)動(dòng)態(tài)加載日志組件的實(shí)現(xiàn),也就是說析既,在你應(yīng)用代碼里躬贡,只需調(diào)用Commons Logging的接口,底層實(shí)現(xiàn)可以是Log4j眼坏,也可以是Java Util Logging拂玻。
  • 后來(2006年),Ceki不適應(yīng)Apache的工作方式宰译,離開了Apache檐蚜。然后先后創(chuàng)建了Slf4j(日志門面接口,類似于Commons Logging)和Logback(Slf4j的實(shí)現(xiàn))兩個(gè)項(xiàng)目沿侈,并回瑞典創(chuàng)建了QOS公司闯第,QOS官網(wǎng)上是這樣描述Logback的:The Generic,Reliable Fast&Flexible Logging Framework(一個(gè)通用缀拭,可靠咳短,快速且靈活的日志框架)。
  • Java日志領(lǐng)域被劃分為兩大陣營(yíng):Commons Logging陣營(yíng)和Slf4j陣營(yíng)蛛淋。
  • Commons Logging在Apache大樹的籠罩下咙好,有很大的用戶基數(shù)。但有證據(jù)表明褐荷,形式正在發(fā)生變化勾效。2013年底有人分析了GitHub上30000個(gè)項(xiàng)目,統(tǒng)計(jì)出了最流行的100個(gè)Libraries诚卸,可以看出Slf4j的發(fā)展趨勢(shì)更好葵第。
  • Apache眼看有被Logback反超的勢(shì)頭,于2012-07重寫了Log4j合溺,成立了新的項(xiàng)目Log4j2, Log4j2具有Logback的所有特性。
  • 如今日志框架已經(jīng)發(fā)展為:Slf4j作為API缀台,實(shí)現(xiàn)分為L(zhǎng)ogback與Log4j棠赛、Log4j2(Commons Logging因?yàn)樾屎虯PI設(shè)計(jì)等問題,現(xiàn)在逐漸淡出舞臺(tái)了)

Slf4j就是在這樣混亂的情況下誕生的,本想可以在這日志框架群雄割據(jù)的年代成為日志標(biāo)準(zhǔn)一統(tǒng)江湖睛约、評(píng)定天下鼎俘,無奈各大梟雄根本不鳥他,繼續(xù)群雄割據(jù)自己玩自己的辩涝,無奈Slf4j只好“曲線救國(guó)”贸伐,以一種委婉的方式不斷提高市場(chǎng)份額,最終成為了事實(shí)上的日志標(biāo)準(zhǔn)怔揩,下面我們就來看看Slf4j是如何“曲線救國(guó)”的怔锌。

3催束、各框架之間有什么關(guān)系?我們?cè)撛趺从茫?/h6>

廢話不多說,我們先上圖:


在這里插入圖片描述

上圖是各框架之間的關(guān)系也是各框架組合使用的方式(由上至下一共分為6層)糊肠,所有的使用方式都由兩部分組成,一部分是日志綁定包(上圖第5層)绘梦,負(fù)責(zé)將具體的日志實(shí)現(xiàn)綁定到Slf4j上嘀掸,上文提到過Slf4j想成為日志標(biāo)準(zhǔn),奈何其他日志框架不認(rèn)可他实幕,不去實(shí)現(xiàn)他提供出來的API吝镣,Slf4j無奈只能自己去實(shí)現(xiàn),所以除了自己的日志實(shí)現(xiàn)Logback外使用其他的日志框架的時(shí)候都需要使用一層日志綁定包來綁定具體的日志實(shí)現(xiàn)昆庇。

另一部分是日志橋接包赤惊,負(fù)責(zé)將應(yīng)用或第三方包中直接使用的日志實(shí)現(xiàn)橋接到Slf4j上,再由Slf4j具體綁定的日志實(shí)現(xiàn)統(tǒng)一輸出凰锡,這樣就解決了遺留項(xiàng)目中直接使用了具體的日志實(shí)現(xiàn)但是還想要接入Slf4j進(jìn)行統(tǒng)一的日志管理未舟,也解決了如業(yè)務(wù)應(yīng)用使用Log4j2某些第三方包使用Log4j或jul等不同日志框架的日志輸出問題,可以將其他日志實(shí)現(xiàn)橋接到Slf4j上掂为,然后由統(tǒng)一的日志實(shí)現(xiàn)完成日志輸出裕膀。

Slf4j就是這樣通過綁定包、橋接包的方式“曲線救國(guó)”實(shí)現(xiàn)了大一統(tǒng)勇哗,最終市場(chǎng)份額不斷擴(kuò)大昼扛,成為了事實(shí)標(biāo)準(zhǔn),Slf4j本來是沒有為L(zhǎng)og4j2提供綁定包欲诺、橋接包的抄谐,但是Log4j2也不得不被趨勢(shì)所迫,自己提供了Slf4j的綁定包(log4j-slf4j-impl-xxx.jar)和橋接包(log4j-to-slf4j-xxx.jar)扰法,整個(gè)日志體系就形成了上圖所示的關(guān)系圖蛹含。

關(guān)于怎么用,我用三個(gè)例子給大家講解一下:

①新業(yè)務(wù)應(yīng)用塞颁,想要使用Slf4j當(dāng)做日志API浦箱,使用Log4j2作為日志實(shí)現(xiàn)

這種情況比較簡(jiǎn)單吸耿,我們只需要引入Slf4j的API包(slf4j-api-xxx.jar)、Log4j2的綁定包(log4j-slf4j-impl-xxx.jar)和Log4j2的日志實(shí)現(xiàn)包(log4j-core-xxx.jar)即可酷窥,比較簡(jiǎn)單就不在贅述了咽安。

②遺留業(yè)務(wù)應(yīng)用,遺留代碼使用Log4j作為日志框架或其他第三方包使用Log4j蓬推,現(xiàn)在想要統(tǒng)一日志框架接入Slf4j作為日志API妆棒,使用Log4j2作為日志實(shí)現(xiàn)

這種情況相較于前一種情況需要多引入一個(gè)Log4j的橋接包(log4j-over-slf4j-xxx.jar)來把直接使用Log4j的遺留代碼橋接到Slf4j上,然后再引入Slf4j的API包(slf4j-api-xxx.jar)沸伏、Log4j2的綁定包(log4j-slf4j-impl-xxx.jar)和Log4j2的日志實(shí)現(xiàn)包(log4j-core-xxx.jar)糕珊,注意這里因?yàn)長(zhǎng)og4j的橋接包的實(shí)現(xiàn)特性,所以需要將原來引入的Log4j的日志實(shí)現(xiàn)包(log4j-xxx.jar)在pom文件中刪除馋评,如果有其他第三方包也使用到了需要將其exclude掉即可

③遺留業(yè)務(wù)應(yīng)用放接,遺留代碼使用Log4j作為日志框架,某些第三方包使用Log4j2留特,現(xiàn)在想要統(tǒng)一日志框架接入Slf4j作為日志API纠脾,使用Log4j2作為日志實(shí)現(xiàn)

這種情況和第二種情況一樣,需要引入Log4j的橋接包(log4j-over-slf4j-xxx.jar)來把直接使用Log4j的遺留代碼橋接到Slf4j上蜕青,然后再引入Slf4j的API包(slf4j-api-xxx.jar)苟蹈、Log4j2的綁定包(log4j-slf4j-impl-xxx.jar)和Log4j2的日志實(shí)現(xiàn)包(log4j-core-xxx.jar),然后排除Log4j的日志實(shí)現(xiàn)包(log4j-xxx.jar)右核,切記不可將Log4j2的橋接包(log4j-to-slf4j-2.xx.jar)引入慧脱,如果引入會(huì)造成循環(huán)調(diào)用最終導(dǎo)致棧溢出,具體細(xì)節(jié)我們?cè)诘谒牟糠謫栴}分析時(shí)在詳細(xì)討論贺喝。

其他橋接包的使用因?yàn)閷?shí)現(xiàn)原理不一樣菱鸥,所以在使用的時(shí)候也會(huì)有所不同,大家在遇到具體問題的時(shí)候可以參考Slf4j官網(wǎng)的文檔查閱:http://www.slf4j.org/legacy.html

3躏鱼、日志框架原理及問題排查

通過上面的幾個(gè)問題我們應(yīng)該已經(jīng)對(duì)Java日志體系有一定的了解了氮采,Slf4j通過橋接包、綁定包“曲線救國(guó)”實(shí)現(xiàn)了大一統(tǒng)成為了事實(shí)標(biāo)準(zhǔn)染苛,所以說到Slf4j就不得不說他的兩個(gè)核心:橋接鹊漠、綁定,為什么Slf4j可以做到不更改代碼實(shí)現(xiàn)日志橋接的呢茶行?Slf4j又是怎么做到綁定不同日志實(shí)現(xiàn)的呢躯概?還有的同學(xué)可能會(huì)有疑問,橋接包這么多畔师,如果有有錯(cuò)誤我們?cè)趺磁挪槟厝⒚遥肯旅嫖彝ㄟ^這兩個(gè)問題來給大家介紹一個(gè)日志橋接的實(shí)現(xiàn)原理和問題排查思路。

1茉唉、為什么Slf4j可以做到不更改代碼實(shí)現(xiàn)日志橋接的呢固蛾?

首先我們來看一下Slf4j官網(wǎng)給出的圖:


在這里插入圖片描述

從上圖可以看出结执,Slf4j的橋接能力是通過log4j-over-slf4j.jar度陆、jcl-over-slf4j.jar艾凯、jul-to-slf4j.jar等jar包實(shí)現(xiàn)的,由于jcl和jul基本已經(jīng)退出日志舞臺(tái)了懂傀,在此我們不在贅述趾诗,如果感興趣可以去Slf4j官網(wǎng)查閱。

下面我們重點(diǎn)介紹一個(gè)Log4j和Log4j2的的橋接包實(shí)現(xiàn)方式:

①Log4j的橋接包(log4j-over-slf4j-xxx.jar)的實(shí)現(xiàn)方式

Log4j的橋接包是有Slf4j實(shí)現(xiàn)的蹬蚁,Log4j官方是不承認(rèn)的恃泪,這就導(dǎo)致Log4j的代碼是沒有給Slf4j開這個(gè)實(shí)現(xiàn)特權(quán)的,所以Slf4j就采用了一種比較粗暴的方式:使用橋接包中的類替換Log4j中的核心類犀斋,我們看下圖橋接包中的類與日志實(shí)現(xiàn)包中的類的包名和類名是完全一致的:


在這里插入圖片描述

在這里插入圖片描述

這樣具體的類實(shí)現(xiàn)就由Slf4j說了算了贝乎,所以上文中介紹Log4j橋接包的使用方式的時(shí)候特別說明需要將Log4j原有的依賴全部排除,因?yàn)椴慌懦蜁?huì)出現(xiàn)重復(fù)的類叽粹,這樣JVM加載的時(shí)候就不一定會(huì)加載到橋接包中的類览效,橋接包就有可能失效了,其實(shí)還有另一種解決方案虫几,依賴于JVM的類加載機(jī)制锤灿,這個(gè)方案我們?cè)谙旅鎲栴}分析的時(shí)候會(huì)詳細(xì)介紹。

②Log4j2的橋接包(log4j-to-slf4j-2.xx.jar)的實(shí)現(xiàn)方式

Log4j2的橋接包是由Log4j2官方實(shí)現(xiàn)的辆脸,所以是官方代碼層面進(jìn)行支持的但校,使用的方式也相對(duì)柔和一下,采用了Java的SPI機(jī)制進(jìn)行的實(shí)現(xiàn)啡氢,如下圖所示状囱,對(duì)SPI具體的實(shí)現(xiàn)方式大家有興趣可以深入了解一下,這里不再展開說明了倘是。


在這里插入圖片描述
2亭枷、Slf4j是怎么做到綁定不同日志實(shí)現(xiàn)的呢?

首先我們還是來看一下Slf4j官網(wǎng)給出的圖:


在這里插入圖片描述

綁定包的實(shí)現(xiàn)就比較統(tǒng)一了辨绊,因?yàn)槭荢lf4j代碼層面進(jìn)行支持的奶栖,這也是Slf4j的設(shè)計(jì)的一部分,所以實(shí)現(xiàn)方式也比較柔和门坷,使用了類似SPI的機(jī)制宣鄙,下面我以Log4j2的綁定包()為例簡(jiǎn)單介紹一下。

首先我們使用Slf4j的時(shí)候所有的Logger的獲取都是從LoggerFactory.getLogger()開始的默蚌,所以我們也從這個(gè)方法開始冻晤,如下圖所示:


在這里插入圖片描述

這里我們主要關(guān)注getILoggerFactory()方法,可以看到首先是通過getILoggerFactory()方法獲取ILoggerFactory的绸吸,然后通過ILoggerFactory的getLogger()方法獲取最終的Logger實(shí)現(xiàn)鼻弧,現(xiàn)在我們看一下getILoggerFactory()方法:


在這里插入圖片描述

這里我們主要關(guān)注紅線圈出來的部分设江,這里我們就確定了,是StaticLoggerBinder來包裝的LoggerFactory攘轩,那是不是所有的綁定包都提供一個(gè)這個(gè)同包名叉存、類名的類就可以實(shí)現(xiàn)不同的日志實(shí)現(xiàn)的綁定了,下面我們來驗(yàn)證一下:


在這里插入圖片描述

果然我們?cè)贚og4j2的綁定包里發(fā)現(xiàn)了這個(gè)同包名度帮、類名的類StaticLoggerBinder歼捏,也發(fā)現(xiàn)了具體的LoggerFactory和Logger實(shí)現(xiàn)(紅框圈出來的部分),至此我們明白了日志綁定是如何實(shí)現(xiàn)的了笨篷,具體的細(xì)節(jié)大家如果有興趣可以自己翻閱源碼深入了解瞳秽。

我們可以看到日志綁定的實(shí)現(xiàn)也挺粗暴的,我也很好奇為什么作者不使用Java的SPI機(jī)制來實(shí)現(xiàn)率翅,大家有興趣也可以自己深入了解一下练俐。

這里其實(shí)有個(gè)小問題可以探討一下,如果我們的應(yīng)用添加了多個(gè)日志綁定包Slf4j會(huì)選擇哪一個(gè)呢冕臭?Slf4j官網(wǎng)給出的解答是會(huì)隨機(jī)選取一個(gè)腺晾,其實(shí)這里并不是一定隨機(jī)的,作者這里的隨機(jī)指的是依賴于JVM的版本浴韭,不同的版本可能綁定的日志實(shí)現(xiàn)是有差別的丘喻,比如我們現(xiàn)在用的JDK1.8版本在JVM加載類的時(shí)候如果遇見了相同包名、類名的類只會(huì)加載第一個(gè)(由上面的介紹我們知道日志綁定包的實(shí)現(xiàn)是由一個(gè)同包名念颈、類名的類StaticLoggerBinder實(shí)現(xiàn)的)泉粉,后面掃描到的類不會(huì)加載,所以在這個(gè)版本是第一個(gè)加載的類生效榴芳,但是這個(gè)規(guī)則在后續(xù)的版本中也可能會(huì)有變化嗡靡,所以在不同版本中可能是隨機(jī)的。還有我們使用的啟動(dòng)方式比如SpringBoot項(xiàng)目的啟動(dòng)和普通Spring項(xiàng)目的啟動(dòng)綁定的日志實(shí)現(xiàn)也是可能有差異的窟感,SpringBoot使用FatJar技術(shù)將所有的第三方都封裝到了一個(gè)Jar包下讨彼,同時(shí)保證了pom.xml中的依賴引入順序,但是普通的Spring項(xiàng)目使用的是Java -cp的方式加載某個(gè)目錄下的第三方包柿祈,這時(shí)候pom.xml中的順序可能就被打亂了哈误,這個(gè)順序依賴于操作系統(tǒng)的文件系統(tǒng)排序,所以這兩種啟動(dòng)方式綁定的日志實(shí)現(xiàn)也是有差異的躏嚎。但是當(dāng)我們的應(yīng)用工程使用固定的JDK版本蜜自、固定的啟動(dòng)方式的情況下綁定的日志實(shí)現(xiàn)也是固定的,只有修改啟動(dòng)方式卢佣、啟動(dòng)參數(shù)重荠、JDK版本的時(shí)候才可能會(huì)發(fā)生變化。

3虚茶、出現(xiàn)日志問題我們應(yīng)該怎么排查戈鲁?

常見的日志問題分為兩類仇参,一類是日志沒有按照我們的日志配置文件的配置進(jìn)行打印,這種問題的原因通常是應(yīng)用中有直接使用日志實(shí)現(xiàn)導(dǎo)致的婆殿,另一類的因?yàn)橐肓送粋€(gè)日志的橋接包與綁定包诈乒,導(dǎo)致打印日志時(shí)進(jìn)入了無限循環(huán)調(diào)用,最終導(dǎo)致拋出StackOverflowError鸣皂。

排查思路基本是一致的抓谴,首先我們需要分析一下當(dāng)前項(xiàng)目中的日志依賴暮蹂,我們用maven的命令(用三個(gè)命令分析全部的日志包)分析一下:

mvn dependency:tree -Dincludes=':*log*:'
mvn dependency:tree -Dincludes=':*jul*:'
mvn dependency:tree -Dincludes=':*jcl*:'
在這里插入圖片描述

分析結(jié)果大致如上圖所示寞缝,然后我們就可以根據(jù)第三部分介紹的搭配使用規(guī)則來排查一下具體的問題了,除此之外我們還可以借助一個(gè)工具Arthas來分析一下我們的日志類到底是從哪個(gè)Jar包加載的仰泻、StaticLoggerBinder到底是從哪個(gè)包加載的荆陆,具體使用方法大家可以去Arthas官網(wǎng)(https://alibaba.github.io/arthas/)查看,結(jié)果如下圖所示:

在這里插入圖片描述

到此基本就可以完全確定問題產(chǎn)生的原因了集侯,我們只需要做相應(yīng)的更改即可被啼。

4、線上問題分析

當(dāng)大家讀到了這里可以說對(duì)Java的日志體系已經(jīng)了解的比較透徹了棠枉,對(duì)當(dāng)前的各日志框架之間的關(guān)系浓体,如何將他們組合使用,橋接的實(shí)現(xiàn)原理辈讶,以及日志問題的排查有了一定的認(rèn)識(shí)命浴,現(xiàn)在我們?cè)俜催^來看我們線上服務(wù)遇見的兩個(gè)問題,看看這兩個(gè)問題究竟是因?yàn)槭裁匆鸬募质侨绾谓鉀Q的生闲。

1、應(yīng)用明明配置了info日志級(jí)別月幌,卻打印大量的debug日志碍讯,導(dǎo)致磁盤IO較高,很快就報(bào)磁盤空間不足告警

通過分析日志依賴確定了是因?yàn)轫?xiàng)目中有第三方包使用的Log4j作為日志框架扯躺,依賴分析如下圖所示:


在這里插入圖片描述

在上圖我們發(fā)現(xiàn)雖然有Log4j的實(shí)現(xiàn)捉兴,但是沒有Log4j的橋接包,所以問題基本可以確定是因?yàn)槿鄙贅蚪影铝寺加铮晕覀円霕蚪影渡叮懦齃og4j的依賴即可。

其實(shí)這里還有另一種方案钦无,我在上文的時(shí)候也說過逗栽,在這里我簡(jiǎn)單介紹一下,因?yàn)槲覀冊(cè)陧?xiàng)目的整個(gè)生命周期里會(huì)不斷地引入新的第三方包和升級(jí)第三方包失暂,所以我們可能這次排除Log4j依賴排除干凈了彼宠,但是不能保證下次還會(huì)引入這個(gè)問題鳄虱,所以這里有個(gè)一勞永逸的辦法,那就是我們讓橋接包中的類優(yōu)先被JVM加載即可凭峡,如果是StringBoot項(xiàng)目拙已,我們只需要把pom.xml中的橋接包依賴移動(dòng)到第一個(gè)即可,普通Spring項(xiàng)目的話就比較麻煩了摧冀,我們需要改動(dòng)一下啟動(dòng)參數(shù)倍踪,改動(dòng)后如下圖所示:


在這里插入圖片描述

上圖的cpath變量最終會(huì)被java -cp $cpath使用,這樣的話就可以保證JVM優(yōu)先加載橋接包中的類了索昂,這個(gè)問題就解決了建车。

2、應(yīng)用服務(wù)啟動(dòng)后報(bào)StackOverflowError錯(cuò)誤椒惨,無法正常提供服務(wù)

服務(wù)在啟動(dòng)的時(shí)候會(huì)拋出StackOverflowError錯(cuò)誤缤至,報(bào)錯(cuò)如下圖所示:


在這里插入圖片描述

從上圖的報(bào)錯(cuò)棧中我們可以看到是發(fā)生了循環(huán)調(diào)用導(dǎo)致,仔細(xì)看包名和類名會(huì)發(fā)現(xiàn)是因?yàn)镾lf4j和Log4j之間發(fā)生了循環(huán)調(diào)用康谆,所以我們只需要使用mvn來分析一下依賴领斥,把Log4j的依賴一一排除就可以了,也可以使用我們上面說的另一種方案讓橋接包被JVM第一個(gè)加載沃暗。

5月洛、參考資料

Slf4j官網(wǎng):http://www.slf4j.org/
Log4j2官網(wǎng):http://logging.apache.org/log4j/2.x/
Logback官網(wǎng):http://logback.qos.ch/
JCL官網(wǎng):http://commons.apache.org/proper/commons-logging/
Arthas官網(wǎng):https://alibaba.github.io/arthas/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市孽锥,隨后出現(xiàn)的幾起案子嚼黔,更是在濱河造成了極大的恐慌,老刑警劉巖忱叭,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隔崎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡韵丑,警方通過查閱死者的電腦和手機(jī)爵卒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撵彻,“玉大人钓株,你說我怎么就攤上這事∧敖” “怎么了轴合?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)碗短。 經(jīng)常有香客問我受葛,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任总滩,我火速辦了婚禮纲堵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闰渔。我一直安慰自己席函,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布冈涧。 她就那樣靜靜地躺著茂附,像睡著了一般。 火紅的嫁衣襯著肌膚如雪督弓。 梳的紋絲不亂的頭發(fā)上营曼,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音咽筋,去河邊找鬼溶推。 笑死,一個(gè)胖子當(dāng)著我的面吹牛奸攻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虱痕,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼睹耐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了部翘?” 一聲冷哼從身側(cè)響起硝训,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎新思,沒想到半個(gè)月后窖梁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夹囚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年纵刘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荸哟。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡假哎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鞍历,到底是詐尸還是另有隱情舵抹,我是刑警寧澤,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布劣砍,位于F島的核電站惧蛹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜香嗓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一爵政、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陶缺,春花似錦钾挟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至苫费,卻和暖如春汤锨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背百框。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工闲礼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铐维。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓柬泽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親嫁蛇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锨并,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容