Log4j启动过程

    用了好久的log4j,但还是不知道Log4j究竟是基于怎样的原理来进行工作,以及为何在项目中除了Log4j之外,还需要一个common-logging来协同进行日志记录。在网上看了下相应介绍,都说common-logging是一个日志的管理框架,具体的事情还是交由log4j来进行记录。决定从源码出发,看看Log4j如何加载配置文件,并进行日志记录。

    将Log4j从网上down下来,并建立工程,将源代码导进去。从Logger入手,一般来说,取得一个Log都是通过

Logger getLogger(Class clazz) {
    return LogManager.getLogger(clazz.getName());
 }

 

转入LogManager,首先应该注意的是这个类的static块, 这个块其实就是一个加载log4j配置文件的过程。即在程序启动之初,在JVM需要加载这个类时,这个初始化块会自动运行,并且加载整个配置,以完成log4j的启动。

Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
......
OptionConverter.selectAndConfigure(url, configuratorClassName,
					   LogManager.getLoggerRepository());

 

上面的所有代码均完成两件事,第一件事就是构造一个ROOT的Logger对象,此对象作为所有logger对象的最上层,其它logger的相应属性均从这个对象进行继承或改写,就好像java里的继承一样,这个类是内定的,不能由配置文件直接指定,且root都是在最顶层的,其他logger均在此下,这样形成一个完整的logger树。下层可以引用上层,上层管理下层。    第二件事则是去寻找配置文件的地址信息,通过各种方法都寻找log4j.xml或log4j.properties文件,然后对文件进行解析。(在此处,通过properties文件进行解析)

OptionConverter.void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy)

 这个方法会最终通过指定的文件解析类(此处是PropertyConfigurator)进行解析,转入

configurator.doConfigure(url, hierarchy)

 这个方法将,url转化成一个properties对象,进行解析。

doConfigure(props, hierarchy);

 进入这个方法

String value = properties.getProperty(LogLog.DEBUG_KEY);//即log4j.debug
    if(value == null) {
      value = properties.getProperty("log4j.configDebug");
      if(value != null) {
      LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
    }

  上面方法读取一个关于log4j自身的debug Level信息,主要用于log4j内部在解析时调用(因为log4j还不能使用logger对象进行写信息,它用到一个LogLog的类,来模拟logger记录,用于在自身解析的过程中输出一些信息),一般来说,这个都用不到。

    主要的信息集中在以下三句话:

configureRootCategory(properties, hierarchy);
configureLoggerFactory(properties);
parseCatsAndRenderers(properties, hierarchy);

 

第一句话用于解析root根对象上的相关配置。

第二句话用于解析loggerFactory(factory用于创建logger对象)

第三句话用于解析除rootLogger之外的其他logger以及render信息。

 

第一句:

  void configureRootCategory(Properties props, LoggerRepository hierarchy) {
    String effectiveFrefix = ROOT_LOGGER_PREFIX;
    String value = OptionConverter.findAndSubst(ROOT_LOGGER_PREFIX, props);
    if(value == null) {
      value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props);
      effectiveFrefix = ROOT_CATEGORY_PREFIX;
    }
......
      Logger root = hierarchy.getRootLogger();
      synchronized(root) {
	parseCategory(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value);
      }
  }

 

上面语句用于从属性文件中寻找logger.rootLogger或logger.rootCategory属性的值然后,再进行配置rootLogger对象信息(如Level,appender等)

  void parseCategory(Properties props, Logger logger, String optionKey,
		     String loggerName, String value) {

  StringTokenizer st = new StringTokenizer(value, ",");
    if(!(value.startsWith(",") || value.equals(""))) {
      if(!st.hasMoreTokens())
	return;

      String levelStr = st.nextToken();
      if(INHERITED.equalsIgnoreCase(levelStr) || 
 	                                  NULL.equalsIgnoreCase(levelStr)) {
	if(loggerName.equals(INTERNAL_ROOT_NAME)) {
	  LogLog.warn("The root logger cannot be set to null.");
	} else {
	  logger.setLevel(null);
	}
      } else {
	logger.setLevel(OptionConverter.toLevel(levelStr, (Level) Level.DEBUG));
      }

    logger.removeAllAppenders();

    Appender appender;
    String appenderName;
    while(st.hasMoreTokens()) {
      appenderName = st.nextToken().trim();
......
      appender = parseAppender(props, appenderName);
      if(appender != null) {
	logger.addAppender(appender);
      }
    }
  }

 

上面这些内容,即是通过logger属性的值(形如debug,A,R)等,然后将值以,分隔进行解析,将第一个字符串定义为logger的Level信息,后面的值则定义为此logger的appender名称。

    当然上面这个方法,即不是尽为rootLogger服务,对于其他logger也调用这个方法,故上面在解析Level时,对root作了单独判断(因为rootLogger的Level不能为空,至少均需要一个值)。处理Level,即将level值简单设置在logger上即可以了。

   接下来即解析appender信息,通过紧接着level后面的字符串,按列表方式进行解析,然后将appender加入logger的appenderList(即要进行信息处理的监听器表)中。进入parseAddpender(解析appender)

    String prefix = APPENDER_PREFIX + appenderName;
    String layoutPrefix = prefix + ".layout";

    appender = (Appender) OptionConverter.instantiateByKey(props, prefix,
					      org.apache.log4j.Appender.class,
					      null);
......
    appender.setName(appenderName);

    if(appender instanceof OptionHandler) {
      if(appender.requiresLayout()) {
	Layout layout = (Layout) OptionConverter.instantiateByKey(props,
								  layoutPrefix,
								  Layout.class,
								  null);
......
	  appender.setLayout(layout);
          PropertySetter.setProperties(layout, props, layoutPrefix + ".");
	  LogLog.debug("End of parsing for \"" + appenderName +"\".");
	}
      }
      PropertySetter.setProperties(appender, props, prefix + ".");
    }
    registryPut(appender);

 上面这个方法,即是解析appender对象,通过log4j.appender.X的前缀(X表示在rootLogger后的appender名称)来取得appender类名,并尝试实例化,然后根据appender来判断是否需要再解析appender的layout(即log4j.appender.X.layout这个键),解析并设置相应属性,最后分别解析appender本身的属性信息和layout的属性信息。(通过ProperSetter这个类,根据javaBean属性映射,将指定后缀后的信息当作一个键,后缀在属性文件中的值作为指定键的值,并将这个键值映射,通过javaBean设置到相应的对象上)

 

    至此,rootLogger即解析完毕。

 

   第二句:解析loggerFactory,略。

   第三句:解析其他logger信息。

  void parseCatsAndRenderers(Properties props, LoggerRepository hierarchy) {
    Enumeration enumeration = props.propertyNames();
    while(enumeration.hasMoreElements()) {
      String key = (String) enumeration.nextElement();
      if(key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
	String loggerName = null;
	if(key.startsWith(CATEGORY_PREFIX)) {
	  loggerName = key.substring(CATEGORY_PREFIX.length());
	} else if(key.startsWith(LOGGER_PREFIX)) {
	  loggerName = key.substring(LOGGER_PREFIX.length());
	}
	String value =  OptionConverter.findAndSubst(key, props);
	Logger logger = hierarchy.getLogger(loggerName, loggerFactory);
	synchronized(logger) {
	  parseCategory(props, logger, key, loggerName, value);
	  parseAdditivityForLogger(props, logger, loggerName);
	}
      } else if(key.startsWith(RENDERER_PREFIX)) {
......
      }
    }
  }

 

这个方法,则主要根据logger.logger为前缀的属性信息进行解析,并根据这个属性信息生成logger,并放在继承树中,设置相应树信息,最后设置其他信息(如appender,level)等,与rootLogger解析基本一致。

 

至此,整个log4j的配置信息已经完成,而这个配置是由JVM保证线程化的(即只能被加载一次),在使用时整个配置已经加载成功,得到的已经是从配置信息中得到的logger对象了。

斗罗大陆叙事体系与战斗系统设计解析 在文学创作与游戏设计中,世界观构建和战斗系统设计是两大核心技术要素。世界观作为故事发生的背景框架,需要融合东西方文化元素并建立量化标准,如《斗罗大陆》中武魂觉醒与魂环等级体系。战斗系统则需突破简单数值对抗,发展出武魂特性、魂技组合与环境互动的三维体系,其中魂导器技术的引入展现了科技与魔法的创新融合。这些设计原理在RPG游戏开发、网络文学创作等领域具有广泛应用价值,特别是对需要长期运营的IP作品,完善的系统设定能有效支撑剧情延展与商业化开发。本文以现象级作品为例,剖析其武魂拟态理论和魂师工业化构思如何成就经典 阅读详情

相关推荐

CentOS7.9 安装 ImageMagick,图片转换为HEIC图像格式

由于ImageMagick7以下不支持heic等图片格式,所以重新安装了ImageMagick7.1版本支持heic格式,在网上找了很多资料,归纳总结并写此文章记录一下。在Linux(CentOS7.9)上安装ImageMagick7.1.1-38。

shmily_i的博客 1941

Log4j输出方式和输出格式的配置

Log4j输出方式和输出格式的配置

Leon_Jinhai_Sun的博客 525

人工智能-CS188 Project 2: Multi-agents

一、项目介绍 项目介绍网页 项目代码下载 本项目是采用Berkeley的CS188课程内容实习二的内容,在这个项目中,我们将为经典版本的Pacman 设计自动算法,包括幽灵。在此过程中,我们将实现 minimax 和 expectimax 搜索并尝试评估函数设计 完成作业只需要完成5个题目,按照项目介绍的步骤进行完成,主要是在multiAgents.py文件中进行补充代码 二、代码详情 1、Question1:Reflex Agent 略 2、Question2:Minimax 套用ppt上的minm

xiten的博客 8285

Log4j学习笔记

Log4j学习笔记1 入门实例2 Log4j基本使用方法2.1 定义配置文件 1 入门实例 我这里在我的Maven项目中先引入log4j的包 <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12<...

Snail_565的博客 1364

对Palantir的本体论的理解

本体论Ontology是Palantir的整个技术架构的核心与基石,它远不止是一个数据模型,而是一个旨在对企业决策本身进行建模的“数字世界的操作系统”。

liuyukuan的专栏 1149

多边形裁剪算法

多边形裁剪算法 刚参加工作就跟多边形刚上了,对于多边形的裁剪做一些简单的总结。 多边形裁剪主要有四种算法 Greiner-Hormann裁剪算法 Sutherland-Hodgman算法 Vatti裁剪算法 Weiler-Atherton裁剪算法 作为一名想要成为优秀算法工程师的程序员,我们不能只会使用,而不知道其原理,倘若如此,我们无法做到应用于本身业务上的定制化的修改。 Greiner–H...

papalqi 6729

Log4J学习【十六】Log4j的默认启动流程一

之前已经看到了使用properties文件或者xml文件配置Log4J的方式。但是,在这两种配置方式中,我们看到,都必须要使用者在整个应用启动之前,使用代码的方式完成Log4J相应配置的读取和加载。我们已经学习了Log4j这么久了,一直会有一个疑问,为什么Log4J就必须让我们自己来配置Log4J?为什么必须让我们自己去写那一段初始化代码?原因其实很简单,在Log4J中,所有的日志总的有一个输出的

HelloWorld的专栏 4205

abaqus2matlab的安装与使用:如何用matlab提取abaqus的odb结果

官网abaqus2matlab官网地址matlab社区地址matlab社区地址在这里可以看到.m文件的源码论文:Abaqus2Matlab: A suitable tool for finite element post-processingabaqus2matlab可以处理.inp、.fil、.odb三种类型的文件。.inp文件:处理功能就在于只是单纯的输出inp文件,由于我自己写了自己的函数,不需要用到这个功能。

qianxin1234的博客 2018

开始使用Log4j

1、分别在src文件夹下面生成一个log4j.properties文件,在工程根目录下,新建一个log文件夹,再在该文件夹下面新建log.log文件和errorlog.log文件。 2、打开log4j.properties文件     log4j.rootLogger=debug, stdout, log log4j.Logger=search,Test   ###Con...

360

解锁RK3588视觉潜能:RGA硬件加速库实战指南

本文深入探讨了如何利用RK3588芯片内置的RGA硬件加速库,解决视觉应用中图像预处理的性能瓶颈。通过实战指南,详细介绍了RGA库在YUV转RGB、图像缩放等核心操作上的应用,相比CPU软处理可大幅降低延迟与CPU占用,从而充分释放RK3588的NPU算力,构建高效的AI视觉预处理流水线。

zeta9的博客 669

国产系统(统信 UOS )漏洞修复方式

2.1 服务器版(单漏洞更新):服务器标准版:yum upgrade-minimal --cve “CVE编号”服务器 D 版:sudo apt update&&sudo apt install “受影响的软件包”1 统信 UOS 漏洞修复方式在线升级修复桌面专业版:通过以下步骤打开在线升级:控制中心–>更新–>更新设置–>打开系统更新、安全更新。安装过程中,请勾选“我已阅读并知晓”,然后点击“开始升级”。2 点击“检查更新”–“全部下载”,如果不想进行系统更新,可以选择只下载“安全更新”。

Reyn_观极 5016

日志实现框架(1):Log4j

什么是Log4J ? Log4j是Apache下的一款开源的日志框架,通过在项目中使用Log4j,我们可以控制日志信息输出到控制台、文件、甚至是数据库中。我们可以控制每一条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程,方便项目的调试 ▎快速入门案例 1. 引入maven依赖(为了方便测试,同步也引入junit) <dependencies> <dependency> <groupId>juni

祝我飞黄腾达 2480

6-2 GPU GART 绑定机制与 TLB 失效

本文详细解析了AMD GPU的GART(Graphics Address Remapping Table)绑定机制实现。主要内容包括: 绑定流程:从ttm_tt_bind()到硬件PTE更新的完整调用链,重点分析amdgpu_gart_bind()函数实现。 关键函数: amdgpu_gart_bind():执行安全检查、记录映射关系、更新页表等操作 amdgpu_gart_map():将CPU页映射为多个GPU页并填充PTE amdgpu_gmc_set_pte_pde():处理硬件特定的PTE格式 内存

图形/计算GPU的驱动与虚拟化技术分享园地 2655

log4j源码分析

1、log4j的启动流程。2、log4j解析配置文件的过程

kangjiabang的博客 301

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

log4j源码解析

log4j启动和加载配置文件的过程分析

kangjiabang的博客 325

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

log4j 源码解析_深入源码解析日志框架Log4j2(一)

前言log4j2是apache在log4j的基础上,参考logback架构实现的一套新的日志系统(我感觉是apache害怕logback了)。log4j2的官方文档上写着一些它的优点:在拥有全部logback特性的情况下,还修复了一些隐藏问题API 分离:现在log4j2也是门面模式使用日志,默认的日志实现是log4j2,当然你也可以用logback(应该没有人会这么做)性能提升:log4j2包含...

weixin_29274969的博客 841

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

关于log4j中log4j.properties和log4j.xml的加载顺序

如果采用log4j输出日志,要对log4j加载配置文件的过程有所了解。 log4j启动时,默认会寻找source folder下的log4j.xml配置文件,若没有,会寻找log4j.properties文件。 转载于:https://www.cnblogs.com/amunamuna/p/8440561.html...

weixin_30784501的博客 498

在tomcat中配置log4j工具

在tomcat中配置log4j工具,最初 #log4j.rootLogger=INFO,A1,R这一行被屏蔽,在tomcat启动时出现提示,No appender之类的,将#去掉之后正常,不知是啥原因。log4j.peoperties文件放于WEB-INF/classes之下即可。将log4j.jar 包放于WEB-INF/lib之下,如果不行,在tomcat/common/lib之下也放

不随黄叶舞秋风 1364

idea中tomcat部署启动不起来,启动后报log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more

启动后如上如; 11-Apr-2022 22:22:27.470 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"] 11-Apr-2022 22:22:27.470 信息 [main] org.apache.catalina.startup.Catalina.start Server startup in 45 ms Connected to server [2022-0.

qq_21687123的博客 1281

log4j 源码解析_log4j2源码解析(2)--LoggerContext

LoggerContext作用及初始化流程根据我们在Log4j初识中的实例可以看出,在不适用日志门面插件slf4j的情况下,获取logger的方式一般为Logger logger = logManager.getLogger(xx.class)可以看到,通常情况下,我们会使用LogManager的静态方法getLogger方法获取logger,下面我们就简要看一下这个方法的流程。public st...

weixin_39569747的博客 986

在项目的classPath 下配置log4j.xml ,为什么没有读取log4j的配置文件它会自己找到

因为在我们引的jar包  log4j-1.2.16.jar里面,在启动时又一个类会自动去找默认的配置文件, 这些是在LogManage.java里面的。默认会去classPath下查找log4j的配置文件。 java虚拟机加载log4j的类(LogManager.class)后,执行静态代码块,这个类中的静态代码块,会加载 log4j的配置文件,依次加载log4j.xml,log4j.

kelan的博客 3129

项目升级log4j2,明明配置了log4j2.xml,可就是报错找不到

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34015860的博客 1624

maven项目启动卡在log4j不动

在开发项目中,遇到错误,要做的首要事情就是查看错误日志。本次遇到的问题,主要是自己在eclipse启动项目,项目启动一半卡住了,控制台没有任何相关错误信息。自己就这样无可奈何了。只是重复的重启项目,清缓存,更新maven,检查jar,非常盲目,没有一点针对性,所以浪费了大量的时间,但是还是没有找到相关错误。最后,经检查发现,项目中使用了log4j作为日志输出,找到相关配置文件:全项目检索log.b...

hou973561160的博客 3073

有关log4j问题

当启动eclipse中的Tomcat时,首先他会自动查找工程中用到的自身文件夹下的common/lib下的jar文件,如果找到的话,就进行加载,然后才查找conf/下的log4j.properties等相关的配置文件,正是因为这样,才会报告没有初始化的信息。如果在common/lib下没有找到工程中要用到的jar文件,就先配置conf/下的配置文件,然后到工程中自身包含的lib下查找所用到的jar

学无止境 781

解决tomcat下log4j(及slf4j-log4j12)和logback冲突问题

遇到诡异问题,记录下解决过程,问题描述: 1、现象。启动过程提示有两个包有相同的类Log相关,后面的LogbackConfigListener报类转换错误。项目启动失败。 2、解决过程。于是找到所有引用Log4j,slf4j-log4j12的地方,exclude。所有地方都写了,maven依赖树也不显示有这两个依赖了。但是啊,lib里面总有这两个包,手动删除,没用,reimport就又进来...

CurrentJ 1702
上一篇: 使用JasperReport输出image图像
下一篇: jquery 插件开发及extend
Fly_m
博客等级 码龄20年 40粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值