本文转自:http://blog.csdn.net/lveliu/article/details/77772828

环境搭建为:maven+tomcat

tomcat 8.5.2 以上会出现改问题(包含8.5.2)

开始:

 警告: Failed to scan [file:/D:/develop/repo/xalan/xalan/2.7.2/xercesImpl.jar] from classloader hierarchy
xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客java.io.FileNotFoundException: D:XXX目录xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件。)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:219)
at java.util.zip.ZipFile.<init>(ZipFile.java:149)
at java.util.jar.JarFile.<init>(JarFile.java:166)
at java.util.jar.JarFile.<init>(JarFile.java:130)
at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:60)
at org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:43)
at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:327)
at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:277)
at org.apache.catalina.startup.ContextConfig.processJarsForWebFragments(ContextConfig.java:1887)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1122)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:771)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:298)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5093)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1405)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1395)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745) 

虽然只是警告,不影响正常使用,但是看着总是那么不爽。

本人使用过的是maven,我以查看maven依赖,不对啊,怎么会查找这个目录下面的xercesImpl.jar,分明不对,原始路径应该是, D:XXX目录xercesxercesImpl2.9.1xercesImpl.2.9.1.jar。

找原因,为什么为加载到D:XXX目录xalanxalan2.7.2xercesImpl.jar这个文件,各种百度谷歌,最后找到问题是tomcat 加载包的问题。tomcat在8.5.2 中 修改了加载jar的方式,8.5.2 版本会解析jar中MANIFEST.MF文件,当该文件包含class-path属性时,会把该属性对象值,解析成需要加载的jar给加载进来。这个就是根本原因。没得办法,只有自降版本到8.5.0就能解决这个问题。为了解决这个问题,花了老子半天时间。

例如xalan.jar中MANIFEST.MF文件,部分截图如下:

 xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

这个就会加载配置的这3个jar,而且寻找路径是xalan.jar所在的文件下寻找。

接下来我们就来看下tomcat的源码,到底是怎么回事。

tomcat 8.5.0 加载jar重要部分如下:

首先调用scanJars扫描jar,重要部分,调用scan方法。

xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

scan方法:

xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

重要部分看红色,这个和8.5.2 版本的方法不一样的地方,这个也是出问题的地方。

先看8.5.0方法:

xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

没有去解析MANIFEST.MF文件。这个正常,接下来我们看8.5.2版本

注意看红色部分

xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

当为jar时,就去调用processManifest该方法,这个方法就是解析MANIFEST文件。下面我们看这个方法:

xalanxalan2.7.2xercesImpl.jar (系统找不到指定的文件)问题-风君雪科技博客

其中就可以看出,去解析了class-path属性,解析对应值,然后加载到需要classPathUrlsToprocess中,这个就是需要加载的jar对象。所以这个就是根本原因。

不知道tomcat在高版本中为什么要这个做,有知道的同学可以解答下。