tomcat加载jar异常问题的分析与解决

 更新时间:2019年04月07日 10:47:36   作者:山东大葱哥  
这篇文章主要给大家介绍了关于tomcat加载jar异常问题的分析与解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用tomcat具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

现象描述:

项目使用springboot启动一个web项目,在启动阶段看到console中出现了异常“1.10.3-1.4.3\hdf5.jar  系统找不到指定的文件”,虽然这些异常不影响项目的正常运行,但作为一个严谨的技术人员,看到这些异常就像见到仇人一样,一定要除之而后快。

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5.jar (系统找不到指定的文件。)
 at java.util.zip.ZipFile.open(Native Method)
 at java.util.zip.ZipFile.<init>(ZipFile.java:225)
 at java.util.zip.ZipFile.<init>(ZipFile.java:155)
 at java.util.jar.JarFile.<init>(JarFile.java:166)
 at java.util.jar.JarFile.<init>(JarFile.java:130)
 at org.apache.tomcat.util.compat.JreCompat.jarFileNewInstance(JreCompat.java:188)
 at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:65)
 at org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:49)
 at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:374)
 at org.apache.tomcat.util.scan.StandardJarScanner.processURLs(StandardJarScanner.java:309)
 at org.apache.tomcat.util.scan.StandardJarScanner.doScanClassPath(StandardJarScanner.java:266)
 at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:229)
 at org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262)
 at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104)
 at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5204)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)
 at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)
 at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
 at java.util.concurrent.FutureTask.run(FutureTask.java)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)

2019-03-29 18:09:08.303 WARN 16940 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner : Failed to scan [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86.jar] from classloader hierarchy

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86.jar (系统找不到指定的文件。)
......
2019-03-29 18:09:08.578 WARN 16940 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner : Failed to scan [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86_64.jar] from classloader hierarchy

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86_64.jar (系统找不到指定的文件。)

项目环境说明

  • tomcat:使用springboot内置版本 8.5.29
  • 使用Maven进行依赖管理
  • spring boot 版本为2.0.1
  • spring 框架 版本为5.0.5
  • 项目引用了Deep Learn 4 Java(一个非常棒的Java的机器学习库)
 <dependency>
 <groupId>org.deeplearning4j</groupId>
 <artifactId>deeplearning4j-core</artifactId>
 <version>1.0.0-beta3</version>
 </dependency>

有问题的jar依赖关系

跟踪分析

既然是在启动阶段报错,那就找到启动类添加断点,一步步跟踪下到底哪个阶段报的错误,然后再分析出错的原因。我跟踪调试了springboot的代码,找到jar的加载位置。主要的几个类和方法如下所示:

跟踪类org.apache.tomcat.util.scan.StandardJarScanner

方法doScanClassPath(...)

该方法会对所有classloader进行遍历,加载每一个classloader中jar包

上图标红处就是关键代码,其中变量classPathUrlsToProcess中存放的是所有待加载的jar信息,主要是jar包路径信息,我们可以看到这里面和我们在maven中看到的jar包是一样的。

  • 方法processURLs(...)

该方法会对当前classloader的所有jar,也就是对classPathUrlsToProcess进行堆栈操作,然后处理每一个jar包。关键代码如下所示。

  • 方法process()

该方法会对每一个jar进行加载及分析处理,该方法中重点关注

processManifest(jar, isWebapp, classPathUrlsToProcess)

  • 方法 processManifest

该方法会处理jar中的Manifest文件,对Manifest文件中的Class-Path进行分隔处理,对其中的内容作为新的依赖jar再插入到classPathUrlsToProcess中(processURLs方法会按照堆栈结果加载其中的jar)

原因分析

其实问题就是出Manifest文件中的classpath,通过分析代码我们知道tomcat除了加载了我们maven管理的jar包之外,还会对jar中的manifest文件进行分析,如果其中存在classpath,他会将其中的内容也添加jar包依赖中,并对这些jar包进行加载。

我们打开其中hdf5-1.10.3-1.4.3.jar的manifest文件作为例子看看错误出在哪里。

大家注意到了没有,这里的jar包没有路径也没有版本号,这就导致tomcat加载的时候按照hdf5-1.10.3-1.4.3.jar的路径进行加载。

然而我们的工程中在对应位置并不存在这些jar,这也就导致了找不到jar的异常。我们工程中实际上有这些jar,只不过路径和名字不一样。在上图左边大家可以看到maven中其实已经有了这些jar,只不过名字后面多了版本号,路径在各自的maven仓库中。

到这里我们已经将出现问题的原因弄清楚了,接下来我们考虑下怎么解决。

解决方案

方案一:

删除Manifest中的classpath或者删除Manifest文件,这样就避免了加载不存在的jar包。但是每次maven更新的时候可能会覆盖掉你的修改,导致异常再次出现。

方案二:

按照加载提示的路径,将对应jar包复制过去并改名去掉版本号,但这样会造成jar冗余,同样的jar会加载两个。

方案三:

降级tomcat版本,使用8.5.0 或以下版本。8.5.0版本中不会对manifest进行分析加载,这样也就不会出现我们的异常了。

方案四

增加一下代码设置不扫描Manifest文件。

 @Bean
 public TomcatServletWebServerFactory tomcatFactory() {
  return new TomcatServletWebServerFactory() {
   @Override
   protected void postProcessContext(Context context) {
    ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
   }
  };
 }

总结:

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • tomcat获取执行的线程池信息和线程堆栈的方法详解

    tomcat获取执行的线程池信息和线程堆栈的方法详解

    这篇文章主要给大家介绍了tomcat获取执行的线程池信息和线程堆栈的方法,文章通过代码示例介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-11-11
  • Tomcat在Linux服务器上的BIO、NIO、APR模式设置方法

    Tomcat在Linux服务器上的BIO、NIO、APR模式设置方法

    下面小编就为大家分享一篇Tomcat在Linux服务器上的BIO、NIO、APR模式设置方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • Tomcat8使用cronolog来进行Catalina.Out日志分割方法

    Tomcat8使用cronolog来进行Catalina.Out日志分割方法

    今天通过本文给大家分享如何使用cronolog来分割catalina.out日志文件,对Tomcat Catalina.Out日志分割方法感兴趣的朋友跟随小编一起看看吧
    2021-09-09
  • Tomcat整体结构简单介绍

    Tomcat整体结构简单介绍

    这篇文章主要介绍了Tomcat整体结构简单介绍,Tomcat的本质是一个Servlet容器。一个Servlet能做的事情是:处理请求资源,并为客户端填充response对象,需要的朋友可以参考下
    2019-07-07
  • 一文详解Tomcat下载安装以及配置

    一文详解Tomcat下载安装以及配置

    这篇文章详细介绍了tomcat的下载安装以及配置,文中有详细的图文和代码示例,需要的小伙伴可以借鉴本文
    2023-04-04
  • Tomcat配置JNDI数据源的三种方式

    Tomcat配置JNDI数据源的三种方式

    项目已经做了很久了,今天终于抽空把一些项目中的东西总结一下,本文就来总结一下Tomcat配置JNDI数据源的三种方式,感兴趣的可以参考一下
    2021-05-05
  • tomcat性能优化方式简单整理

    tomcat性能优化方式简单整理

    这篇文章主要介绍了tomcat性能优化方式简单整理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 一文告诉你如何解决Tomcat乱码问题(很详细!)

    一文告诉你如何解决Tomcat乱码问题(很详细!)

    这篇文章主要给大家介绍了关于如何解决Tomcat乱码问题的相关资料,还给大家介绍了tomcat窗口中文乱码的解决方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • Tomcat配置必备的10个小技巧用法总结

    Tomcat配置必备的10个小技巧用法总结

    Tomcat具有免费、跨平台等诸多特性,并且更新得很快,现在非常的流行,你所需要做的就是:按照你的需求配置Tomcat,只要你正确配置,Tomcat一般都能适合你的要求,下面是一系列关于Tomcat的配置技巧,希望对你有所帮助
    2023-05-05
  • Tomcat无法映射到activiti-app导致activiti无法启动页面的解决方法

    Tomcat无法映射到activiti-app导致activiti无法启动页面的解决方法

    这篇文章主要介绍了Tomcat无法映射到activiti-app导致activiti无法启动页面的解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11

最新评论