现象描述:
项目使用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 (系统找不到指定的文件。)
项目环境说明
<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包是一样的。
该方法会对当前classloader的所有jar,也就是对classPathUrlsToProcess进行堆栈操作,然后处理每一个jar包。关键代码如下所示。
该方法会对每一个jar进行加载及分析处理,该方法中重点关注
processManifest(jar, isWebapp, classPathUrlsToProcess)
该方法会处理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); } }; }
总结:
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对小牛知识库的支持。
本文向大家介绍SpringBoot2 JPA解决懒加载异常的问题,包括了SpringBoot2 JPA解决懒加载异常的问题的使用技巧和注意事项,需要的朋友参考一下 jpa解决懒加载异常 在我上一遍文章上进行行修改,SpringBoot2 实现JPA分页和排序分页 实体类上改: 控制器验证 我大概实现了一下,具体的如果大佬找到更好的方法或者发现我的方法是错的,希望各位大佬提醒一下!感谢! 补充:Sp
本文向大家介绍关于 jQuery Easyui异步加载tree的问题解析,包括了关于 jQuery Easyui异步加载tree的问题解析的使用技巧和注意事项,需要的朋友参考一下 想要实现从本地中加载json文件,通过事件来动态的插入到ul中时,遇到了一小bug html中代码是这样的 js中的代码 起初是想通过一个按钮的点击事件来动态的加载tree的内容就是如上代码,addAttr2Tree 是
svg-sprite-loader加载图标异常问题 正常的图标 加载异常的图标 请问是什么原因? 无
使用指南 - 分析云 - 分析云常见问题 Q: 分析云版本中的事件数据量是什么? A: 事件数据量是指该站点每天记录的事件日志的总量,每次分析请求的数据量如超出该上限会进行抽样。 Q: 全埋点数据可支持事件回溯1个月是什么意思? A: 全埋点功能会自动记录访客的元素点击事件,圈选事件后,可基于全埋点数据进行一个月的回溯,防止错埋、漏埋等情况。 Q: 购买分析云后,基础统计具体哪些资源提升了? A:
本文向大家介绍深入分析Tomcat无响应问题及解决方法,包括了深入分析Tomcat无响应问题及解决方法的使用技巧和注意事项,需要的朋友参考一下 问题描述 生产环境下有几台tomcat,但突然某个时候发现所有的请求都不能响应了,由于我们的web server使用的是nginx,会将请求反向到tomcat上,所以起初怀疑是nginx就没有收到请求,但查看日志后发现,nginx中大量出现499的
本文向大家介绍thinkPHP线上自动加载异常与修复方法实例分析,包括了thinkPHP线上自动加载异常与修复方法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了thinkPHP线上自动加载异常与修复方法。分享给大家供大家参考,具体如下: 项目遇到一个奇怪的问题,本地代码正常,服务器上却不正常。 经过测试,应该是自动加载出了问题,尝试了各种方法, 1.手动加载,发现好麻烦,没完没了