在一次项目上线后,发现了一个奇怪的问题,经过对源码的阅读调试终于解决,具体经过是这样的:

问题描述:tomcat7下面部署多个项目,log4j的日志输出会集中输出到一个项目中,就算配置了日志文件的绝对路径也是一样的。

解决方法:log4j.jar在每个项目中单独加到lib下

解决过程:先从log4j入手分析,在项目启动时调试org.apache.log4j.FileAppender,输出获取文件路径是绝对路径,应该是没有问题的,其实在正常的启动下也会输出该日志
信息: Set web app root system property: 'RootPath' = [H:\Project\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\cpa-1.0\]
信息: Set web app root system property: 'CpaRootPath' = [H:\Project\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\cpa\]
log4j是基于spring进行初始化的,到这里怀疑是spring容器实例化作用域是否有问题,但是本地调试又正常的,发布到tomcat才有问题,好奇看了一下之前的部署的项目,发现日志是没有影响的;

  调试log4j的初始化源码,使用PropertyConfigurator.configure(configFilename)进行初始化测试,日志的输出路径配置会被addAppender到LogManager.getLoggerRepository()实例的repositorySelector变量中,而LogManager中的repositorySelector是静态初始化的;当然到目前为止仍然不会有问题,关键是tomcat的jar共享,放在shared/lib下面的共享包会被URLClassLoader加载,单独放到项目lib下面的jar包会被WebAppClassLoader加载,区别就在这里,关于URLClassLoader和WebAppClassLoader加载为什么会引起这种问题还要继续深入分析tomcat启动加载。

  了解Java和JVM的一定知道,JVM中通常有三层默认的类加载器,分别是启动(Bootstrap)类加载器、标准扩展(Extension)类加载器和系统(System)类加载器。这三者每两者间都是父子关系,即前者是后者的父亲或者双亲类加载器,并由此构建了一个“双亲委派关系”,或叫“代理”关系。当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?

  • 首先当前线程的类加载器去加载线程中的第一个类(假设为类A)。

    注:当前线程的类加载器可以通过Thread类的getContextClassLoader()获得,也可以通过setContextClassLoader()自己设置类加载器。

  • 如果类A中引用了类B,Java虚拟机将使用加载类A的类加载器去加载类B。
  • 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

  上面是jvm加载class的加载器,当tomcat启动时会为每个app分配了一个WebappClassLoader ,这样来避免多个app会加载相同jar包的问题,WebappLoader的parent是org.apache.catalina.loader.WebappClassLoaderBase,细看源码WebappClassLoaderBase直接继承于java.net.URLClassLoader类,最终继承于java.lang.ClassLoader类这样多个app就能共享tomcat的类库;WebappClassLoader的源码中发现,在进行findClass时会先试图自己加载类,找不到则请求parent来加载,这里和java的双亲委托模式是不同的,所以如果log4j放到项目lib下面会被当前项目的WebAppClassLoader加载并初始化静态实例,因为每个项目都被单独分配了WebAppClassLoader,这样jvm就能区分来自不同项目的各个类(热部署使用的就是该技术)。

总结:如果不深入的了解jvm和tomcat类加载器是很理解该问题是如何解决的,经过分析源码,并写了demo进行测试才实践出上述结论,实践出真理!

解决tomcat下面部署多个项目log4j的日志输出会集中输出到一个项目中的问题的更多相关文章

  1. 使用log4j将日志输送到控制台、文件或数据库中

    转: 使用log4j将日志输送到控制台.文件或数据库中 2018-09-07 00:45:08 keep@ 阅读数 2880更多 分类专栏: 其它   版权声明:本文为博主原创文章,遵循CC 4.0 ...

  2. 如何在Eclipse中彻底修改一个项目名称

    在实际工作中,有时候为了赶时间,往往通过复制项目得到一个成型的框架.那么怎么才可以彻底修改项目名称呢? 1.web.xml 2.工作空间中找到当前项目下.project文件 3.工作空间中找到当前项目 ...

  3. 如何把VS2015中本地的一个项目建立远程的Git Repository

    在项目开发中,我在本地自己电脑上用VS2015建立了一个项目,比如项目名字叫做Luke.Test 那么,接下来,我如何把这个项目签入到远程的Git Repository里去呢. 方法如下 先进入远程R ...

  4. 解决tomcat同时部署两个SpringBoot应用提示InstanceAlreadyExistsException

    问题描述:Caused by: javax.management.InstanceAlreadyExistsException: com.alibaba.druid.pool:name=primary ...

  5. 解决tomcat同时部署两个SpringBoot应用报异常InstanceAlreadyExistsException

    问题描述:Caused by: javax.management.InstanceAlreadyExistsException: com.alibaba.druid.pool:name=primary ...

  6. 关于Eclipse中复制粘贴一个项目后的操作

    今天在做一个小Demo,内容和之前的项目有些类似就直接复制过来了,项目名修改了,web.xml的项目名也修改了,可是部署到Tomcat之后,以这个新项目名进行访问就会出现404的错误,只可以使用复制之 ...

  7. c# winform 在一个窗体中使用另一个窗体中TextBox控件的值——解决办法

    [前提]一个winform应用程序项目中,窗体B,需要使用 窗体A 中一个TextBox控件的值,进行计算等操作. [解决方案] 1.在窗体A中定义:public static double a;// ...

  8. 如何在maven项目中引用领一个项目

    1 有两个项目 maven01  和maven 02,想在maven 02中引用maven01的方法,该如何操作呢 maven01中Factory类中的方法 public class Factory ...

  9. IDEA中每次拷贝一个项目的时候必须标记一下配置文件resources,否则报错

随机推荐

  1. springmvc 事务回滚说明

    Spring中的@Transactional(rollbackFor = Exception.class)属性详解 序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollb ...

  2. 基于Activiti工作流引擎实现的请假审核流程

    概要 本文档介绍的是某商用中集成的Activiti工作流的部署及使用,该框架用的Activiti版本为5.19.0.本文档中主要以一个请假流程为例子进行说明,该例子的流程图如下: 这是一个可以正常运作 ...

  3. Daily Scrumming* 2015.12.17(Day 9)

    一.团队scrum meeting照片 二.成员工作总结 姓名 任务ID 迁入记录 江昊 任务1077 https://github.com/buaaclubs-team/temp-front/com ...

  4. Daily Scrumming* 2015.12.10 今天集体请假一天

    今天由于所有成员均在进行编译原理实验的相关工作,全体请假一天.......

  5. BlogPublishTool - 博客发布工具

    BlogPublishTool - 博客发布工具 这是一个发布博客的工具.本博客使用本工具发布. 本工具源码已上传至github:https://github.com/ChildishChange/B ...

  6. Smart Disk -- proposed by Liyuan Liu

    Need 如今,照相渐渐得成为了人们的日常举动.几乎所有的人都在随时随地得照相.手机,相机,平板越来越多的设备对照相进行了支持,同时, 照片以一种前所未有的速度渐渐淹没我们的文件夹.而寻找照片,对照片 ...

  7. [BUG随想录] expat不兼容BUG

    本周五软工团队项目的第一次前后端全部对接时,出了一个蛋疼的错误. 最初起因是小丽叔出于安全的考虑,使用守护进程来跑Web服务器.守护进程(Daemon)是运行在后台的一种特殊进程,如果服务器用root ...

  8. Manjaro Linux 没有声音

    在Multimedia中的PulseAudio Volume Control中的设置可以解决

  9. 作业三(下)安装VS2013

    VS2013 今天常识安装Microsoft Visual Studio 2013,虽然 直接在软件管家上下载,一键安装,但是还是遇到许多问题,安装过程相当的艰难,花了好多时间.但是在尝试多次后成功的 ...

  10. java自定义注解学习(三)_注解解析及应用

    上篇文章已经介绍了注解的基本构成信息.这篇文章,主要介绍注解的解析.毕竟你只声明了注解,是没有用的.需要进行解析.主要就是利用反射机制在运行时进行查看和利用这些信息 常用方法汇总 在Class.Fie ...