1. 前言

  从写代码开始,就陆陆续续接触到了许多日志框架,较常用的属于LOG4J,LogBack等。每次自己写项目时,就copy前人的代码或网上的demo。配置log4j.properties或者logback.properties就能搞定。这种思想一直持续到最近,前几天写了一个小demo,放在liunx上跑的时候竟然报stackOverFlow异常,仔细看异常信息,log4j-over-slf4j与slf4j-log4j12共存导致stack overflow异常,这一刻终于来了,我不得不去正式日志框架了。

2. 解决方案

  先贴一下我的解决方案。既然报冲突了,不管三七二十一,先删除一个jar包就OK!第一种解决方案直接在项目的WEB-INF\lib下删除slf4j-log4j12.jar包。

  1. cd /WEB-INF/lib
  2. rm -rf slf4j-log4j12-1.7..jar

  这种方案只是临时方案,再次打包部署时还会出现此问题。第二种方案是在pom.xml找到引用此JAR包的地方,我是因为引入了zookeeper,自带了此JAR包。使用<exclusion>标签排除此JAR包。或者使用<packagingExcludes>标签在打包时排除此JAR包。个人推荐使用<packagingExcludes>,因为我的<exclusion>标签不管用,此处不做详解,直接贴代码!

  1. <dependency>
  2. <groupId>org.apache.zookeeper</groupId>
  3. <artifactId>zookeeper</artifactId>
  4. <version>3.4.6</version>
  5. <exclusions>
  6. <exclusion>
  7. <artifactId>slf4j-log4j12</artifactId>
  8. <groupId>org.slf4j</groupId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-war-plugin</artifactId>
  4. <configuration>
  5. <packagingExcludes>WEB-INF/lib/slf4j-log4j12-1.7.25.jar</packagingExcludes>
  6. </configuration>
  7. </plugin>

3. 基本日志框架之间关系

  类比java的面向接口编程思想,JAVA日志框架分为接口层,实现层,还多了个桥接层,桥接层联系接口层和实现层。

  

  接口层:SELF4J,COMMONS-LOGGING

  实现层:LOG4J,LOGBACK,JDK-LOOGING,LOG4J2

  以上为通用的日志框架实现(即实现)和门面(即接口)。日志门面的出现很大程度缓解了日志系统的混乱,很多库的作者不在使用具体的日志框架实现了,而是去使用接口层,即面向接口编程。此处,贴一段话,方面更能理解。

  应用程序直接使用这些具体日志框架的API来满足日志输出需求当然是可以的,但是由于各个日志框架之间的API通常是不兼容的,这样做就使得应用程序丧失了更换日志框架的灵活性。比直接使用具体日志框架API更合理的选择是使用日志门面接口。日志门面接口提供了一套独立于具体日志框架实现的API,应用程序通过使用这些独立的API就能够实现与具体日志框架的解耦,这跟JDBC是类似的。最早的日志门面接口是commons-logging,但目前最受欢迎的是slf4j。日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,就好像JDBC与各种不同的数据库之间的结合需要对应的JDBC驱动一样。

4. StackOverFlow异常分析

  

  上图来自SLF4J官网。如图,上层都是使用SLF4JAPI对外暴露接口。SLF4JAPI使用的是slf4j-api.jar包。接着下层各个日志框架的实现就不一样了,最左边的是slf4j的一个空实现。第二列和第五列是logback和slf4j的一个简单实现,这2个框架没有使用所谓的桥接器,直接继承slf4j,实现slf4j的接口。log4j和jul的实现是要依靠桥接器,如上,slf4j-log412.jar和slf4j-jdk14.jar就是桥接器,分别连接slf4j,log4j和slf4j,jul。下面的log4j.jar和JVM runtime便是具体实现。

  其他日志系统转掉回slf4j,如果只存在slf-4j转到日志系统实现类,便不会存在StackOverFlow的异常。如果我们使用log4j日志系统,但又想使用别的日志系统,此时就要使用从日志系统到slf4j的桥接类 log4j-over-slf4j,这个库定义了与log4j一致的接口(包名、类名、方法签名均一致),但是接口的实现却是对slf4j日志接口的包装,即间接调用了slf4j日志接口,实现了对日志的转发。

  既然存在这么多桥接器,万一我的系统中存在slf4j -> log4j 和 log4j -> slf4j的桥接器。。。。就会出现互相委托,无限循环,堆栈溢出的状况。所有就会有出现异常。slf4j关于桥接器的详细介绍参考slf4j官方网站:https://www.slf4j.org/legacy.html

  比如,我现在想使用slf4j的实现类logback日志框架

  1. 引入slf4j & logback日志包和slf4j -> logback桥接器;

  2. 排除common-logging、log4j、log4j2日志包;

  3. 引入jdk-logging -> slf4j、common-logging -> slf4j、log4j -> slf4j、log4j2 -> slf4j桥接器;

  4. 排除slf4j -> jdk-logging、slf4j -> common-logging、slf4j -> log4j、slf4j -> log4j2桥接器。

 

  

Java日志框架总结的更多相关文章

  1. Java程序员最常用的8个Java日志框架

    转自:http://www.codeceo.com/article/8-java-log-framework.html 作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用 ...

  2. 转:Java程序员最常用的8个Java日志框架

    作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug:在 ...

  3. Java 日志框架终极教程

    概述 对于现代的 Java 应用程序来说,只要被部署到真实的生产环境,其日志的重要性就是不言而喻的,很难想象没有任何日志记录功能的应用程序被运行于生产环境中.日志 API 所能提供的功能是多种多样的, ...

  4. Java日志框架那些事儿

    文章首发于[博客园-陈树义],点击跳转到原文Java日志框架那些事儿. 在项目开发过程中,我们可以通过 debug 查找问题.而在线上环境我们查找问题只能通过打印日志的方式查找问题.因此对于一个项目而 ...

  5. Java基础学习总结(40)——Java程序员最常用的8个Java日志框架

    作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug:在 ...

  6. Java-最常用的Java日志框架整理

    Java-最常用的Java日志框架整理 前言 Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日 ...

  7. java日志框架系列(4):logback框架xml配置文件语法

    1.xml配置文件语法 由于logback配置文件语法特别灵活,因此无法用DTD或schema进行定义. 1.配置文件基本结构 配置文件基本结构:以<configuration>标签开头, ...

  8. Java日志框架:SLF4J,Common-Logging,Log4J,Logback说明

    Log4j  Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Syslog守护进程等 ...

  9. java日志框架slf4j与log4j

    日志记录自然是非常重要的,但恐怕能记住slf4j与log4j等日志框架配置的人就很少了,这个东西不难,只是配置好后很少会去动它,开发新项目一般也是从其他项目拷贝,或者参照文档 废话不多说,先说log4 ...

随机推荐

  1. WIZnet-io6Library下载及使用

    概观 io6Library是一个IPv6集成库,可以轻松集成和管理使用WIZnet硬连线双TCP / IP堆栈控制器(WIZCHIP)产品系列的用户应用程序. io6Library用于管理依赖于用户特 ...

  2. Go中的命名规范

    1.命名规范 1.1 Go是一门区分大小写的语言. 命名规则涉及变量.常量.全局函数.结构.接口.方法等的命名. Go语言从语法层面进行了以下限定:任何需要对外暴露的名字必须以大写字母开头,不需要对外 ...

  3. GBK和UTF-8的区别

    我们这里将以最简单最容易理解的方式来描述GBK和UTF8的区别,以及它们分别是什么.   GBK编码:是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符 ...

  4. 从零开发一款自己的小程序UI组件库(二)

    写在前面:从零开发一款自己的小程序UI组件库(一) 上节我们讲到初始化组件库模板.模板文件概述.模板上传npm以及npm包文件下载至本地并运用到项目.这节我们继续,内容主要有基础UI组件库的搭建(bu ...

  5. JS鼠标吸粉特效

    HTML <canvas id=canvas></canvas> CSS * { margin: 0; padding: 0; } html { overflow: hidde ...

  6. Duilib的圆环形 进度条 实现(网易云信版本)

    /** @file CircleProgress.h* @brief 圆环型进度条控件,圆环中间可以有文本(如85%)* @copyright (c) 2019-2022, NetEase Inc. ...

  7. python3虚拟环境中解决 ModuleNotFoundError: No module named '_ssl'

    前提是已经安装了openssl 问题 当我在python3虚拟环境中导入ssl模块时报错,报错如下: (py3) [root@localhost Python-3.6.3]# python3 Pyth ...

  8. Flink的JobManager启动(源码分析)

    都知道Flink中的角色分为Jobmanager,TaskManger 在启动脚本里面已经找到了jobmanager的启动类org.apache.flink.runtime.entrypoint.St ...

  9. Oracle EM的重新配置和界面语言修改

    实际在国内的DBA日常工作中,几乎很少会用到EM进行日常管理.但在Oracle的考试中,为了快速完成某些场景的应答,还是推荐使用EM进行操作的. 1.重新配置EM 2.修改界面语言 1.重新配置EM ...

  10. FaceNet人脸识别研究

    https://github.com/WindZu/facenet_facerecognition (代码) https://segmentfault.com/a/1190000015917420?u ...