Java 类加载冲突本质原因以及常见规避套路

1、背景

某天,业务的一个妹子过来找我,说升级到framework-bom 1.9.3,应用启动不了,但是本地启动是ok的。报错信息如下:


image.png

2、起因

我们中间件团队也对各种starter 做了封装。比如健康检测模块,注意箭头指向的位置


image.png

而 spring 框架也有此封装,但是里面没有 <font color='red'> getMaxThreads </font> 方法


image.png

仔细看看上面的两个截图的箭头指向的位置,会发现 ManagementServerProperties 类的全路径一致。

3、讨论

  • 有人建议业务的妹子,把两者的 jar 的依赖换个位置。我当时想着,这项目都部署完毕了,已经没有 maven 事情了,肯定是类加载机制的问题。
  • 我当时请教一下别人,别人说,可能是 springboot 框架记住了jar 的顺序了。咦,纳闷了,springboot 还能干这个事情?如果不使用springboot的话,肯定也有类似的加载的问题,肯定是不是框架层次的问题了。

4、初步结论。

类加载冲突,导致出现问题。删除中间件封装的类即可。


心中的问题一致困扰着我???得要研究清楚


5、Maven 的依赖规则

  • 短路优先(就近原则)
  • 先声明先优先。

6、如何排除某些jar 呢?

  • idea 安装 maven healper 插件。如何使用,在这里就写了。


    image.png
  • maven help

如何查看 java 应用加载 jar 的顺序呢?

  • 如何查看 idea 启动的时候,加载 jar 的顺序呢


    image.png
  • 部署应用的机器查看,使用 java -verbose 命令


    image.png


类如何被JVM 加载的

双亲委派原则如下图所示

image.png

最终原因是啥呢

JDK 官方文档:https://docs.oracle.com/javase/7/docs/technotes/tools/solaris/classpath.html
The order in which the JAR files in a directory are enumerated in the expanded class path is not specified and may vary from platform to platform and even from moment to moment on the same machine. A well-constructed application should not depend upon any particular order. If a specific order is required then the JAR files can be enumerated explicitly in the class path.
翻译:
相同目录下,JAR文件在JVM 中加载的顺序是无法保证,并且可能因平台而异,甚至在同一台计算机上也可能因时间而异。构造良好的应用程序不应依赖于任何特定的顺序。如果需要特定的顺序,那么可以在类路径中显式指定加载JAR文件的顺序。

至此,问题基本明了了,基本底层也搞清楚了。

后续步骤

  • 在应用检测层次,需要检测出来 类冲突,需要使用 maven-enforcer-plugin 插件,正好我也负责代码检测项目(jar 冲突,版本禁用,SQL 审批等),已经罗列到议程中。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。