java学习基地

微信扫一扫 分享朋友圈

已有 1886 人浏览分享

从一个Logger异常开始梳理Java日志体系

[复制链接]
1886 0
醋蠡个启动非常开端

SpringBoot项目正在启动时报仓库溢出,毛病以下。

  1. Exception in thread "main" java.lang.StackOverflowError
  2.     at org.apache.logging.log4j.util.StackLocator.getCallerClass(StackLocator.java:108)
  3.     at org.apache.logging.log4j.util.StackLocator.getCallerClass(StackLocator.java:121)
  4.     at org.apache.logging.log4j.util.StackLocatorUtil.getCallerClass(StackLocatorUtil.java:55)
  5.     at org.apache.logging.slf4j.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:42)
  6.     at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:46)
  7.     at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:29)
  8.     at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
  9.     at org.apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:39)
  10.     at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:37)
  11.     at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:29)
  12.     at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:52)
  13.     at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:29)
  14.     at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
赶钙代码

日记输出很少很少,皆是反复,开端判定是递回挪用太深招致栈溢出,成绩泉源指背日记接心。

阐发那个非常呈现的详细缘故原由之前,有须要先理解一下现有的Java日记系统。关于Java使用来讲,日记记载是一个必不成少的工具。经由过程日记,开辟职员能够更加便利的逃踪线上成绩,阐发营业数据等涤耄

而开辟职员正在停止项目开辟的时分,常常会被项目中碰到的各类日记框架弄的蒙头转向,常常没有明白正在一个类中该当用哪一个框架去挨印日记。因而,觉得有须要对Java的日记系统停止一次梳理,弄分明各个日记框架之前的干系,以便本人往后用起去可以驾轻就熟。

1、Java日记系统开展过程

正在实践开辟过程当中,Java的日记框架系统之以是会给编程职员带去一种紊乱的觉得,底子缘故原由是Java日记框架出有同一的利用尺度。

  • Log4,正在最后的上古时期,法式员们并出有现秤弈日记框架,java开辟者们只能利用本初的System.out.println(), System.err.println()大概e.printStackTrace()。经由过程把debug日记写到StdOut流,毛病日记写到ErrOut流,去完成使用法式运转形态的记载。如许有一个很年夜的成绩,那便是没法定造化,而且日记的输出粒度不敷细。因而1999年,Ceki Gülcü创立了Log4j项目,并险些成了Java日记框架的实践尺度。
  • JUL,Log4j做为Apache基金会的一员,Apache期望将Log4j引进jdk,不外被sun企业公司回绝了。随后,sun模拟Log4j,正在jdk1.4中完成了JUL即java.util.logging。
  • JCL,厥后为了完成将日记接心取完成解耦,Apache推出了JCL即Apache Commons Logging。JCL直义了一套日记接心,详细完成由Log4j或JUL去完成。JCL基于静态绑定去完成日记的记载,正在利用时只需求用JCL界说的接心去编写代码便可,法式实正运转时会查抄classpath中的详细完成,因而能够自在挑选是有log4j仍是JUL去完成日记功用。
  • Slf4j&Logback,厥后,Java日记年夜佬Ceki Gülcü分开了Apache本人单干,前后创立了Slf4j战Logback两个项目。Slf4j是一个日记门里,只供给接心,能够撑持Logback、JUL、log4j等完成;Logback做为年夜佬本人供给的详细完成,相较于log4j有更快的施行速率战更完美的功用。
  • log4j2,最初,Apache为了不Slf4j战Logback,渐渐代替JCL战Log4j ,推出裂旁祭阅还击之做log4j2。log4j2没有兼容log4j,机能得到了很年夜的提拔。因而,我们便看到了云云多的日记框架并存的场面。
2、日记门里、桥接器取日记完成2.1、门里形式

比间接利用详细日记框架更公道狄住择是利用日记门里接心。日记门里接心供给了一套自力于详细日记框架完成的API,使用法式经由过程利用那些自力的API就可以够完成取详细日记框架的解耦,那跟JDBC是相似的。最早的日记门里接心是commons-logging,但今朝最受欢送的是SLF4J。

SLF4J(Simple logging Facade for Java)

意义为简朴日记门里,它是把差别的日记体系的完成停止了详细的笼统化,只供给潦粘一的日记利用接心,利用时只需求根据其供给的接心办法停止挪用便可,因为它只是一个接心,并非一个详细的能够间接零丁利用的日记框架,以是终极日记的格局、记载级别、输出方法等皆要经由过程接心绑定的详细的日记体系去完成,那些详细的日记体系便有log4j2、log4j、logback、java.util.logging等,它们才完成了详细的日记体系的功用。

日记门里正在利用时,能够静态大概静态的指定详细的日记框架完成,完成凉心战完成的解耦,使得映雩能够灵敏狄住择日记的详细完成框架。另外一种便是详细的日记体系,它供给了详细的日记接话柄现,使用法式经由过程详细完成施行日记挨印的功用。

那为何要将日记的系统弄那么庞大呢,简朴一个完成没有就行了吗,为何分红门里取完成?要解问那个成绩,需求回忆一下门里形式。

门里形式,其中心为U解部取一个子体系的通讯,必需经由过程一个同一的表面工具停止,使得子体系更容易于利用。

如今,我们能够回到最后的成绩了,日记系统为何要利用SLF4J做为门里呢?

利用slf4j后有益于按照本人实践的需供改换详细的日记体系,好比,之前利用的详细的日记体系为log4j,念改换为logback时,只需求删除log4j相干的jar,然后参加logback相干的jar战日记设置文件便可,而没有需求窜改详细的日记输出办法,试念假如出有接纳这类方法,当您当钡统中日记输出有不计其数条时,您要改换日记体系将是何等宏大的一项工程。假如您开辟的是一个里背公家利用的组件或大众效劳模块,那末必然要利用slf4的┞封种情势,那有益于他人正在挪用您的模块时连结战他体系中利用同一的日记输出。

2.2、sl4j取详细日记框架的分离

Java日记系统当前大致能够分为三个部门:日记门里接心、桥接器、日记框架详细完成。门里接心取日记完成上里曾经引见过了。

那末甚么是桥接器呢?所谓“桥接器”,不外便是对某套API的真完成,这类完成并非间接来完成API所声明的功用,而是来挪用有相似功用的此外API。如许便完成了从“某套API”到“此外API”的转调。假如同时存正在A-to-B.jar战B-to-A.jar那两个桥接器,那末能够设想当使用法式开端挪用A大概B的API时,会发作甚么事。那便是最开端引出的谁人stack overflow非常的根本道理。

下图去自SL4J民网文档。

能够看到slf4j取详细日记框架分离的计划有许多种。固然,每种计划的最上层(绿色的使用层)皆是同一的,它们背下皆是间接挪用slf4j供给的API(浅蓝色的笼统API层),依靠slf4j-api.jar。然后slf4j API背下再怎样做便十分自在了,险些可使用一切的详细日记框架。

留意图中的第两层是浅蓝色的,看左下角的图例可知那代表笼统日记API,也便是道它们没有是详细完成。假如像右边第一种计划那样基层出有跟任何详细日记框架完成相分离,那末日记是没法输出去的( 那里没有肯定能否能够会默许输出到尺度输出 )。(搜刮公家号Java知音,复兴“2021”,收您一份Java口试题宝典)

图中第三层较着便没有如第1、两层那末整洁齐整了,由于那里曾经开端触及到了详细的日记框架。

起首看第三层中心的两个湖蓝色块,那是适配层,也便是桥接器。右边的slf4j-log4j12.jar桥接器看名字便明白是slf4j到log4j的桥接器,一样,右侧的slf4j-jdk14.jar便是slf4j到Java本诞辰志完成的桥接器了。它们当敝位层别离是洞喀的日记框架完成,log4j的完成代码是log4j.jar,而jul完成代码曾经包罗正在了JVM runtime中,没有需求零丁的jar包。

再看第三层其他的三个深蓝色块。它们三个也是详细的日记框架完成,可是却没有需求桥接器,由于它们自己便曾经间接完成了slf4j API。slf4j-simple.jar战slf4j-nop.jar那两个不消多道,看名字便明白一个是slf4j的简朴完成,一个是slf4j的空完成,平常用途也没有年夜。而logback之以是也完成了slf4j API,是由于logback战slf4j出自统一人之脚。

第三层一切的灰色jar包皆带有白框,那暗示它们皆间接完成了slf4j API,只是湖蓝色的桥接器对slf4j API的完成并非间接输出日记,而是转来挪用此外日记框架声明的API。

2.3、其改日志框架桥接到sl4j

假如只存正在上里那些从sfl4j到其改日志框架的桥接器,能够借没有会出甚么成绩。可是实践上另有别的一类桥接器,它们的感化跟上里的刚好相反,它们将别的日记框架的API转调到slf4j的API擅埽

下图去自SL4J民网文档。

上图展现了今朝为行能宁静天从此外日记框架API转调回slf4j的一切三种情况。

以左上角第一种情况为例,当slf4j蹬鲢利用的详细完成是logback时,上层许可桥接到slf4j的日记框架API有log4j战jul。jcl固然没有是甚么日记框架的详细完成,可是它的API仍旧是可以被转调回slf4j的。要念完成转调,办法便是图上列出的用特定的桥接器jar交换失落原本的日记框架jar。

看完三种情况当前,会发明险些一切其改日志框架的API,包罗jcl的API,皆可以随便的转调回slf4j。可是有一个独一当鞭造便是转调回slf4j的日记框架不克不及跟slf4j当前利用的蹬鲢详细日记完成框架不异。

那个限定便是为了避免A-to-B.jar跟B-to-A.jar同时呈现正在类途径中,从而招致A战B不断不断天相互递回挪用,最初仓库溢出。今朝那个限定并非经由过程手艺包管的,仅仅靠开辟者本人包管,那也是为何slf4j民网上要夸大一切公道的方法只要上图的三种情况。

假定slf4j+log4j:一个详细的日记操纵的历程,起首挪用slf4j的API接心,然后 slf4j将恳求转收给slf4j-log4j12去处置,那个实邻编译时期静态绑定好的。然后slf4j-log4j12最初经由过程log4j去完成日记操纵。

假如再减一个 log4j-over-slf4j会如何?实在日记恳求又从头挨回给 slf4j,构成一个环形

到那里,本文一开端所展现的谁人非常的道理根本曾经分明了。别的,经由过程上图借能够看出能够会呈现相似非常的组开不单单是log4j-over-slf4j战slf4j-log4j12,slf4j民网借指出了别的冶:jcl-over-slf4j.jar战slf4j-jcl.jar

2.4、multiple SLF4J bindings正告

实在本文一开端的启动非常是能够提早制止的,利用maven编译工程时能够发明以下multiple SLF4J bindings正告,假如间接疏忽此正告,启动spring boot使用便会报上里提到的stackOverFlow非常。

上边正告大要意义是道logback-classic包战log4j-slf4j-impl包,闭于org/slf4j/impl/StaticLoggerBinder.class 那个类发作聊驽突。缘故原由是一个接心,被两个完成类完成了,但是法式正在启动获得时,只念获得一个。那个接心是:org.apache.logging.slf4j.Log4jLoggerFactory

两个完成类别离是:

  • logback-classic包中的org.slf4j.impl.StaticLoggerBinder
  • log4j-slf4j-impl包org.slf4j.impl.StaticLoggerBinder

发作那个毛病的缘故原由,起首logback日记的开辟者战log4j的开辟是统一小我私家,而SpringBoot默许日记是矫β的logback日记。可是正在从前盛行的日记倒是log4j ,并且许多的第三圆东西皆露有log4j的引进。而我玫邻项目开辟中,不免会引进林林总总的东西包,以是,根本上SpringBoot项目,假如没有留意,必定会呈现这类抵触的。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

举报 使用道具

回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

1

粉丝

308

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Archiver|手机版|java学习基地 |网站地图

GMT+8, 2021-6-18 15:57 , Processed in 1.018594 second(s), 29 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.