最新文章

一个Tomcat类加载问题

一个Tomcat类加载问题

背景 一个Tomcat实例中运行了三个应用,其中一个对接了Apereo的CAS系统。现在要求另外两个系统也对接CAS系统,问题就出现了: 应用启动后打开其中两个应用的任何一个,登录完成后系统都没有问题。唯独首选打开第三个,其他两个报错ClassNotFoundException: org.apache.xerces.parsers.SAXParser。 发现这个类来自xerces:xercesImpl:jar:2.6.2,使用mvn dependency:tree发现是被xom:xom:1.1简洁引用。 分析 CAS client jar中使用XMLReaderFactory创建XMLReader,首次创建会从classpath中查找META-INF/services/org.xml.sax.driver文件,这个文件里的内容是一个类的全名。比如xercesImpl中该文件的内容是org.apache.xerces.parsers.SAXParser。 找到之后会将类名保存在XMLReaderFactory的静态变量_clsFromJar,并标记不会再查找org.xml.sax.driver文件。找不到的话则使用com.sun.org.apache.xerces.internal.parsers.SAXParser类。 然后再使用当前线程的ContextClassLoader对类进行加载,这里的的ContextClassLoader是一个WebAppClassLoader的实例。 同时XMLReaderFactory类是被BootStrapClassLoader加载的,为三个应用共享。 Tomcat类记载机制 Tomcat中有四个位置可以存放Java类库:/commons、/server、/shared和各Web应用的WEB-INF/lib目录。 /commons目录中的类库可以被Tomcat和所有Web应用使用 /server目录中的类库只能被Tomcat使用 /shared目录中的可以被所有Web应用的使用,但是对Tomcat不可见 各Web应用的WEB-INF/lib目录中的类库则只能被该的应用使用 Tomcat的使用CommonClassLoader、CatalinaClassLoader、SharedClassLoader、WebAPPClassLoader加载对应目录中的类库。 Bootstrap、Extension、Application是虚拟机使用的系统类加载器。 类的加载使用双亲委派机制(Parent-Delegation)。 Bootstrap | Extension | Application | System | Common / \ Catalina Shared / \ WebApp1 ... WebApp2 | | Jasper Jasper 解决方案 在另外两个应用中添加xerces:xercesImpl:jar:2.

About Me

张晓辉

英文名 Addo。 资深程序员,LF APAC 开源布道师,CNCF Ambassador,云原生社区管委会成员,公众号“云原生指北”作者,微软 Azure MVP。 曾任职于汇丰软件、唯品会、数人云、小鹏汽车,有多年的微服务和基础架构实践经验,主要工作涉及微服务、容 …

进一步了解