Log4j2 - Unable to invoke factory method in class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFileAppender for element RollingFile

问题与分析

在使用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}.

参考链接

原文地址:https://www.cnblogs.com/yulinlewis/p/10211599.html

时间: 2024-11-05 02:20:32

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

关于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实现序列化接口即可

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

root cause java.lang.NoClassDefFoundError: org/apache/logging/log4j/spi/AbstractLoggerWrapper 网上资料比较少,最后查到是mybatis 3.2.7的bug,升级到3.3.0就好了 详见:https://github.com/mybatis/mybatis-3/issues/234  emacarron modified the milestone: 3.2.8, 3.3.0 on 10 Oct 2014

Attempt to invoke virtual method &#39;void android.support.v7.app.ActionBar.setHomeButtonEnabled(boolean)&#39; on a null object reference

[Android]getActionBar()为null的解决方法总结 setContentView(R.layout.activity_main);android.support.v7.app.ActionBar actionBar = getSupportActionBar();actionBar.setHomeButtonEnabled(true);actionBar.setDisplayShowHomeEnabled(true);actionBar.setIcon(R.mipmap.ic

c++ 设计模式8 (Factory Method 工厂方法)

5. "对象创建"类模式 通过"对象创建"类模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 5.1 工厂方法 动机: 在软件系统中,经常面临着创建对象的工作:由于需求的变化,需要创建的对象的具体类型经常变化. 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种"封装机制"来避免客户程序和这种"具体对象创建工作"的紧耦合? 代码示例

com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method

查看了网友们的错误原因, 需要进行实例化的类没有进行实例化,具体没有实例化的类会在错误信息中显示,在错误信息中搜索"Serializable"即可找到将其实现序列化可消除错误. 是在使用Dubbo提供服务是在主机上启动了虚拟机的网络,在Windows中具体可以,在运行中输入"CMD"在CMD窗口中输入"ifconfig"命令查看,如果有其他除本地的网络链接,通过命令或者将其手动禁止,再启动Dubbo服务可以解决问题. 防火墙对应端口没有开启 我这

工厂方法(Factory Method)模式

一.工厂方法(Factory Method)模式 工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟的子类中. 工厂方法模式是简单工厂模式的进一步抽象和推广.由于使用了多态性,工厂方法模式保持了简单工厂模式的有点,而且客服了它的缺点. 在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给予子类去做.这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节.这使得工厂方法模式可以允许

DesignPattern_Java:Factory Method Pattern

工厂方法模式 Factory Method :(虚拟构造函数模式 Virtual Constructor,多态性工厂模式 Ploymorphic Facoty) Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. 定义一个创建产品对象

工厂方法模式(Factory Method Pattern)

2. 工厂方法模式(Factory Method Pattern) 2.1. 模式动机 现在对该系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的按钮工厂类,再定义具体的工厂类来生成圆形按钮.矩形按钮.菱形按钮等,它们实现在抽象按钮工厂类中定义的方法.这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,这一

设计模式之六:工厂方法模式(Factory method Pattern)

工厂方法(Factory Method)模式就是定义一个创建对象的工厂接口,将实际创建工作推迟到子类当中. 核心工厂类不再负责具体产品的创建,仅提供了具体工厂子类必须实现的接口,这样核心类成为一个抽象工厂角色,这样做的好处是工厂方法模式可以使系统在不修改具体工厂角色的情况下进行引进新的产品. 在Factory Method模式中,工厂类与产品类往往具有平行的等级结构,它们之间一一对应. 从上图可以看出,工厂方法模式有四个角色: 抽象工厂角色(ICreator):是工厂方法模式的核心,与应用程序无