log4j:ERROR Failed to rename

来源:互联网 发布:足球大师2捏脸数据库 编辑:程序博客网 时间:2024/05/31 06:21

log4j:ERROR Failed to rename

重命名日志文件时错误。

log4j.properties配置如下:

log4j.rootLogger=INFOlog4j.logger.access= INFO,reglog4j.appender.reg=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.reg.layout=org.apache.log4j.PatternLayoutlog4j.appender.reg.File=D:\\secureCRT\\sync.loglog4j.appender.reg.DatePattern='.'yyyy-MM-ddlog4j.appender.reg.layout.ConversionPattern=%d - [%p] - [%F\:%L] %m%nlog4j.logger.access2= INFO,A3log4j.appender.A3=org.apache.log4j.RollingFileAppenderlog4j.appender.A3.layout=org.apache.log4j.PatternLayoutlog4j.appender.A3.File=D:\\secureCRT\\sync.loglog4j.appender.A3.MaxFileSize=500KBlog4j.appender.A3.layout.ConversionPattern=%d - [%p] - [%F\:%L] %m%n

运行时只使用了reg,没有使用A3。

原因:reg日志记录器配置的是DailyRollingFileAppender,每天产生新文件,而产生新文件是用的File.renameTo(),

在这出错了。google发现,在windows原因是有其他的进程在占用该日志文件,检查发现我用记事本打开了这个文件(D:\\secureCRT\\sync.log),于是关掉记事本,再次运行,仍然报这个错误。有点奇怪了,除了reg还会有什么进程在占用这个文件呢?

然后又检查log4j.properties,发现reg和A3的日志文件时配置的同一个(见上面配置文件),会不会这个导致的?

于是,把A3暂且注释掉,运行通过,产生了新的文件!

也就是说,虽然没有用到A3,但log4j仍然会加载该配置并实例化了。


为了验证,查看源码(版本1.2.16):

log4j的使用是从如下地方开始的:

Logger logger = Logger.getLogger(Test.class);

进入Logger.getLogger(Test.class):

static public  Logger getLogger(Class clazz) {    return LogManager.getLogger(clazz.getName());}
进入LogManager类,注意有一段static代码区,是用于在第一次加载该类时初始化log4j的:

static {    // By default we use a DefaultRepositorySelector which always returns 'h'.    // 以DEBUG级别生成RootLogger    Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));    repositorySelector = new DefaultRepositorySelector(h);    ......    //加载系统变量"log4j.configuration",已不推荐使用    String configurationOptionStr = OptionConverter.getSystemProperty(DEFAULT_CONFIGURATION_KEY,  null);      String configuratorClassName = OptionConverter.getSystemProperty( CONFIGURATOR_CLASS_KEY,  null);      URL url = null;      // 先加载log4j.xml,如果失败,则加载log4j.properties(推荐使用xml)      // if the user has not specified the log4j.configuration      // property, we search first for the file "log4j.xml" and then      // "log4j.properties"      if(configurationOptionStr == null) {          url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);         if(url == null) {           url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);         }      } else { try {   url = new URL(configurationOptionStr); } catch (MalformedURLException ex) {   // so, resource is not a URL:   // attempt to get the resource from the class path   url = Loader.getResource(configurationOptionStr);  }       }              ......         // 加载配置文件            OptionConverter.selectAndConfigure(url, configuratorClassName,    LogManager.getLoggerRepository());      ......  } 
进入OptionConverter.selectAndConfigure():

void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {   Configurator configurator = null;   String filename = url.getFile();   if(clazz == null && filename != null && filename.endsWith(".xml")) {     clazz = "org.apache.log4j.xml.DOMConfigurator";   }   if(clazz != null) {     LogLog.debug("Preferred configurator class: " + clazz);     configurator = (Configurator) instantiateByClassName(clazz,   Configurator.class,   null);     if(configurator == null) {      LogLog.error("Could not instantiate configurator ["+clazz+"].");      return;     }   } else {     configurator = new PropertyConfigurator();   }   configurator.doConfigure(url, hierarchy);  }

根据配置文件类型,选择不同的加载类,xml则为DOMConfigurator,properties则为PropertyConfigurator

然后调用doConfigure()来加载。

以PropertyConfigurator来看,进入PropertyConfigurator.doConfigure():

public void doConfigure(String configFileName, LoggerRepository hierarchy) {    Properties props = new Properties();    FileInputStream istream = null;    try {      istream = new FileInputStream(configFileName);      props.load(istream);      istream.close();    }      ......    // 加载propertie配置文件    // If we reach here, then the config file is alright.    doConfigure(props, hierarchy);  }

进入加粗的方法里,最后会看到三行代码:

configureRootCategory(properties, hierarchy);//加载RootLoggerconfigureLoggerFactory(properties);// 加载LoggerFactory(用于后面生成Logger)parseCatsAndRenderers(properties, hierarchy);//加载其他日志记录器(自定义的)

从上面的源码可以看出,log4j在第一次调用时,即加载整个配置文件并初始化,所有就可以理解上面这个问题了,虽然A3没有使用,

但仍然加载初始化了,并占有日志文件,导致reg无法rename。





0 0
原创粉丝点击