问题与分析

在使用Log4j2时,虽然可以正确读取配置文件并生成log文件,但偶然发现控制台打印了异常信息如下:

2018-12-31 17:28:14,282 Log4j2-TF-19-ConfiguratonFileWatcher-6 ERROR Unable to invoke factory method in class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:235)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:135)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:959)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:899)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:891)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:514)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:238)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:250)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:547)
at org.apache.logging.log4j.core.LoggerContext.onChange(LoggerContext.java:670)
at org.apache.logging.log4j.core.config.ConfiguratonFileWatcher$ReconfigurationRunnable.run(ConfiguratonFileWatcher.java:68)
at java.lang.Thread.run(Thread.java:748)

将控制台的所有信息都复制出来,仔细查找,又发现了相关的异常信息:

2018-12-31 17:28:14,241 Log4j2-TF-19-ConfiguratonFileWatcher-6 ERROR Unable to create file logs/${ctx:domainId}/CNTCore.log java.io.IOException: The filename, directory name, or volume label syntax is incorrect
at java.io.WinNTFileSystem.canonicalize0(Native Method)
at java.io.WinNTFileSystem.canonicalize(WinNTFileSystem.java:428)
at java.io.File.getCanonicalPath(File.java:618)
at .... 2018-12-31 17:28:14,280 Log4j2-TF-19-ConfiguratonFileWatcher-6 ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: ManagerFactory [...] unable to create manager for [logs/${ctx:domainId}/CNTCore.log] with data [...] java.lang.IllegalStateException: ManagerFactory [...] unable to create manager for [logs/${ctx:domainId}/CNTCore.log] with data [...]
at org.apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:115)
at org.apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:114)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:188)
at ....

看起来是因为配置文件里的RollingFile使用到了${ctx:domainId}导致了这个问题。百度了下,发现了log4j2的jira issue:Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile

该问题和我遇到的一样,而在jira里有comment如下:

Question: Does system property logfile have a value?

结合项目的配置文件log4j2.xml:

<RollingFile name="logfile" immediateFlush="true" fileName="logs/${ctx:domainId}/CNTCore.log"
filePattern="logs/${ctx:domainId}/CNTCore.log.%d{yyyy-MM-dd-a}.gz" append="true">
<PatternLayout>
<pattern>%d %t %p %X{TracingMsg} %c - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1" />
</Policies>
</RollingFile>

可以看出,这个异常是由于RollingFile使用到了${ctx:domainId},而该变量值是null,导致无法创建对应的RollingFile文件到磁盘。但是这个domainId是通过ThreadContext把值put进去的,不可能是null,从最终的效果来看,这个变量其实也是拿到了值的,因为对应的日志文件以及存在于磁盘上了。

既然如此,为什么还会出现这个异常呢?通过观察控制台可以发现,每过一段时间就会出现一次该异常。从异常中可以看到ConfiguratonFileWatcher,好像有些明白为什么了。

ConfiguratonFileWatcher是用来扫描配置文件是否被改动过的,在配置文件中设置的扫描间隔是30s:

<configuration monitorInterval="30">
....
</configuration>

由于扫描文件时另外起一个线程去扫描的,而${ctx:domainId}的值是存放于ThreadContext中的,ThreadContext是线程安全的,同一个key对应的value在不同线程中是不一定相同的。而对于新启动的线程来说,并没有将domainId的值存放进去,于是新线程在扫描配置文件的RollingFile时,自然是无法获取到${ctx:domainId}的值,故而每隔一段时间就会报上边的异常。

解决方法

方案一

既然问题是因为扫描配置文件是否改动造成的,那么只要将动态加载的功能关闭就行了,如下:

<configuration monitorInterval="0">
....
</configuration>

方案二

如果希望不关闭动态加载配置文件的功能,可以将domainId的值存放到System.properties里:

System.setProperty("domainId", "xxx");

然后通过${sys:xxx}的方式来获取该properties的值:

<RollingFile name="logfile" immediateFlush="true" fileName="logs/${sys:domainId}/CNTCore.log"
filePattern="logs/${sys:domainId}/CNTCore.log.%d{yyyy-MM-dd-a}.gz" append="true">
<PatternLayout>
<pattern>%d %t %p %X{TracingMsg} %c - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1" />
</Policies>
</RollingFile>

在log4j2中关于这些变量取值有以下这些种类:

Prefix Context
bundle Resource bundle. The format is ${bundle:BundleName:BundleKey}. The bundle name follows package naming conventions, for example: ${bundle:com.domain.Messages:MyKey}.
ctx Thread Context Map (MDC)
date Inserts the current date and/or time using the specified format
env System environment variables. The formats are ${env:ENV_NAME} and ${env:ENV_NAME:-default_value}.
jndi A value set in the default JNDI Context.
jvmrunargs A JVM input argument accessed through JMX, but not a main argument; see RuntimeMXBean.getInputArguments(). Not available on Android.
log4j Log4j configuration properties. The expressions ${log4j:configLocation} and ${log4j:configParentLocation} respectively provide the absolute path to the log4j configuration file and its parent folder.
main A value set with MapLookup.setMainArguments(String[])
map A value from a MapMessage
sd A value from a StructuredDataMessage. The key "id" will return the name of the StructuredDataId without the enterprise number. The key "type" will return the message type. Other keys will retrieve individual elements from the Map.
sys System properties. The formats are ${sys:some.property} and ${sys:some.property:-default_value}.

参考链接

Log4j2 - Unable to invoke factory method in class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFileAppender for element RollingFile的更多相关文章

  1. 关于dubbo调度时出现Request processing failed; nested exception is com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method insertTestTb in the service cn.cuibusi.core.service.TestTbService.的解决办法

    在用dubbo跨项目调度service时出现如下错误: 错误原因:pojo没有实现序列化 解决方法:在pojo实现序列化接口即可

  2. mybatis + log4j2 问题 java.lang.NoClassDefFoundError: org/apache/logging/log4j/spi/AbstractLoggerWrapper

    root cause java.lang.NoClassDefFoundError: org/apache/logging/log4j/spi/AbstractLoggerWrapper 网上资料比较 ...

  3. java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.love5/com.example.love5.Main11Activity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.

    若有 java.lang.RuntimeException和 java.lang.NullPointerException: Attempt to invoke virtual method 'voi ...

  4. 4.工厂方法模式(Factory Method)

    耦合关系:       动机(Motivation):    在软件系统中,由于需求的变化,"这个对象的具体实现"经常面临着剧烈的变化,但它却有比较稳定的接口.    如何应对这种 ...

  5. springBoot集成Elasticsearch抛出Factory method 'restHighLevelClient' threw exception; nested exception is java.lang.NoSuchFieldError: IGNORE_DEPRECATIONS

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restHighLeve ...

  6. C#面向对象设计模式纵横谈——5.Factory Method 工厂方法模式(创建型模式)

    动机 (Motivation) 在软件系统中,经常面临着“某个对象”的创建工作; 由于需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何应对这种变化?如何提供一种“封装机制” ...

  7. C#设计模式系列:工厂方法模式(Factory Method)

    1. 工厂方法模式简介 1.1 定义 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法模式是以一个类的实例化延迟到其子类. Factory Method模式用于在不指定待创建 ...

  8. 小菜学习设计模式(三)—工厂方法(Factory Method)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

  9. 浅谈C++设计模式之工厂方法(Factory Method)

    为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...

随机推荐

  1. Linux环境下安装ActiveMq

    一.准备安装的tar包 1.将安装包放在服务器上:apache-activemq-5.10.2.tar.gz 2.将安装包解压:tar -zxvf apache-activemq-5.10.2.tar ...

  2. 数组/字符串/ Math / 方法示例

    数组 Array concat  数组的合并 <script> var north = ["北京","上海","深圳"]; va ...

  3. POJ1456 Supermarket —— 贪心 + 路径压缩优化

    题目链接:http://poj.org/problem?id=1456 Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Subm ...

  4. 基于BASYS2的VHDL程序——交通灯(状态机版)

    请尊重作者版权,转载注明源地址:http://www.cnblogs.com/connorzx/p/3694618.html 使用了状态机,增加了可读性和用户体验. library IEEE; use ...

  5. 测试工程师面试题之:给你印象最深的Bug

    有人看到别人在侵淫面试技巧,什么<程序员面试宝典>,或者<面试测试工程师须知>等等,就会嗤之以鼻.他会觉得这不是“投机取巧”吗,最重要的还是踏实提高自己的能力. 非常同意这种看 ...

  6. 【概念】SVG(2)

    Style <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg&qu ...

  7. 在Angular.js中的H5页面调用Web api时跨域问题处理

    /// <summary> /// 被请求时 /// 在Angular.js中的H5页面调用Web api时跨域问题处理 /// </summary> /// <para ...

  8. 烂笔头——JAVA/JSP

    学艺不精,一些小零头放这里备忘 Object[] obj = (Object[])list.get(i);//取list的某个项目 jsp中出现out.println( )和System.out.pr ...

  9. bootstrap 学习笔记(1)---介绍bootstrap和栅格系统

    学习前端许久,对于布置框架和响应浏览器用html 和javascript 写的有点繁琐,无意间看到这个框架,觉得挺好用的就开始学习了,但是这个框架上面有很多知识,不是所有的都要学的,故将学习笔记和觉得 ...

  10. 洛谷 1072 Hankson 的趣味题——质因数界限讨论

    题目:https://www.luogu.org/problemnew/show/P1072 思路是把每个数质因数分解,答案对于每个质因数的次数有选择的区间,通过这个计算. 指数的限制就是上限是b1, ...