log4j:ERROR Failed to rename

log4j:ERROR Failed to rename

重命名日志文件时错误。

log4j.properties配置如下:

log4j.rootLogger=INFO

log4j.logger.access= INFO,reg
log4j.appender.reg=org.apache.log4j.DailyRollingFileAppender
log4j.appender.reg.layout=org.apache.log4j.PatternLayout
log4j.appender.reg.File=D:\\secureCRT\\sync.log
log4j.appender.reg.DatePattern='.'yyyy-MM-dd
log4j.appender.reg.layout.ConversionPattern=%d - [%p] - [%F\:%L] %m%n

log4j.logger.access2= INFO,A3
log4j.appender.A3=org.apache.log4j.RollingFileAppender
log4j.appender.A3.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.File=D:\\secureCRT\\sync.log
log4j.appender.A3.MaxFileSize=500KB
log4j.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);//加载RootLogger
configureLoggerFactory(properties);// 加载LoggerFactory(用于后面生成Logger)
parseCatsAndRenderers(properties, hierarchy);//加载其他日志记录器(自定义的)

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

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值