问题与分析

在使用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. 2014 ACM-ICPC Beijing Invitational Programming Contest

    点击打开链接 Happy Reversal Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      J ...

  2. Struts status

       #status.odd        是否奇数行    #status.count    当前行数    #status.index    当前行的序号,从0开始[#status.count=# ...

  3. ACM2016级新生第三周训练赛

    本次是弱校题解-比赛链接 备用链接 题目还是比较基础,比较简单.认真补题,学会学习. A -人见人爱A^B 题解: 求 A的B次方,我们可以用循环进行累乘操作,进而计算出次方.因为题目要求只需要求出最 ...

  4. codeforces 701A A. Cards(水题)

    题目链接: A. Cards 题意: 问两个数的和相同,怎么组合; AC代码: #include <iostream> #include <cstdio> #include & ...

  5. June 26,程序破解

    1.android程序破解练习初级 方法一: 文件名:KeygenMe#1.apk工具:ApktoolGui v2.0 Final 先用ApktoolGui v2.0 Final反编译成java通过查 ...

  6. SDOI2017 Round1 Day1 题解

    不知道有几个AK的,除了出题人SB搬了个BZOJ3779以外,应该没什么因素阻碍AK吧.要是SCOI考这套题多好. BZOJ4816 数字表格 SB反演,推出答案为$\prod_{i=1}^nf^{\ ...

  7. maven的常用构建命令

    mvn clean:删除项目根目录中的target目录

  8. win10 下安装linux子系统

    一.开发人员选项 打开控制面板->程序与功能->启用或关闭windows功能 勾选    [适用于linux的windows子系统]    选项 打开win10设置 找到更新与安全 启动开 ...

  9. bzoj 1096 仓库建设 —— 斜率优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1096 设 f[i] 为 i 作为最后一个仓库时前 i 个工厂的答案,最后的答案当然是 f[n ...

  10. POJ2274(后缀数组应用)

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25272   Accepted: 10 ...