jar包冲突解决的一些经验
开篇
最近因为一些原因遇到了一些jar包冲突的实际问题,包括tomcat无法加载某lib包,hadoop上mr任务依赖lib版本问题,tomcat依赖包找不到等等。
这些问题归结起来能够很好的检验几个关键问题:1、双亲委派原则的理解;2、maven依赖传递的原则;3、java classpath路径先后顺序问题。
双亲委派原则
说明:
- 1、首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回。
- 2、如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用parent.loadClass(name, false);).或者是调用bootstrap类加载器来加载。
- 3、如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器的findClass方法来完成类加载。
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
实际案列
- 如果指定名称的类已经加载过了就不会再次加载,这个问题属于双亲委派范围,存在两种情况会遇到这个问题。
- 1、多版本jar包依赖当中,由于低版本jar包中类已经加载导致高版本jar包中同名的类无法加载,从而导致使用了高版本的jar包依赖的函数无法找到,因为该函数只在高版本中存在。
- 2、不同的jar包却存在同名路径的类,如package+class的路径是完全一致的,那就会导致两个不同的jar包的同名类只有一个类会被加载,从而同样找不到函数问题。
maven依赖原则
maven的依赖顺序
- 1、依赖路径最短优先原则
一个项目Demo依赖了两个jar包,其中A-B-C-X(1.0) , A-D-X(2.0)。由于X(2.0)路径最短,所以项目使用的是X(2.0)。 - 2、pom文件中申明顺序优先
如果A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven会根据pom文件声明的顺序加载,如果先声明了B,后声明了C,那就最后的依赖就会是X(1.0)。 - 3、覆写优先
子pom内声明的优先于父pom中的依赖。
maven的解决冲突
- 1、通过们mvn dependency:tree查看依赖树,通过maven的依赖原则来调整坐标在pom文件的申明顺序是最好的办法。
- 2、通过exclude排除一些间接依赖,或者把依赖的jar包调整到最前面,按照maven加载顺序最前面加载了jar包后间接引用就不会生效了。
classpath路径先后问题
Of particular importance, and much consternation, the class loader will load classes in the order they appear in the classpath. Starting with the first classpath entry, the class loader visits each specified directory or archive file attempting to find the class to load. The first class it finds with the proper name is loaded, and any remaining classpath entries are ignored.
说明:
- 上面说明了,java xx -classpath ".;a.jar;b.jar;" 时,如果a.jar和b.jar有重名的类,那么会以a.jar的为准,忽略b.jar的,因为jvm按照-classpath参数的路径先后顺序去load类,后续加载的同名的类会被忽略。
案例分享
- hadoop集群上跑MR任务(自行打的jar包,jar包中依赖的protobuf-java版本高于hadoop集群自身lib目录当中的protobuf-java版本),导致每次先加载低版本的protobuf-java版本然后报方法找不到错误。
- 实际当中针对上面的问题,会在把高版本的jar包放在当前目录并在代码当中把当前目录添加到classpath的最前面,保证先加载高版本的jar包。
tomcat无法加载jar包
真实案例
错误信息 java.lang.NoClassDefFoundError: com/beibei/ai/base/UserModel catalina.log日志内容 Apr 5, 2013 1:38:26 PM org.apache.catalina.loader.WebappClassLoader validateJarFile INFO: validateJarFile(/home/frodo/apache-tomcat-7.0.37/webapps/hive/WEB-INF/lib/base-0.0.42-SNAPSHOT.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
说明:
- 查看/logs/catalina.log定位到具体的日志。
- 和tomcat当中加载的类javax.servlet.Servlet发生冲突导致类无法加载。
- Stack Overflow问题
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
大数据好学习吗?如何快速掌握大数据开发技能
大数据好学习吗?如何快速掌握大数据开发技能?经常被学员问到:大数据好学吗?想学大数据怕学不会等问题。我想说的是,大数据在当下是个非常热门的话题,大数据在深刻的影响着这个世界,在促进传统行业升级改造、引领新兴产业和新兴应用蓬勃发展、提升社会运行和管理效率等方面,大数据正引发新一轮革命。大数据是时代潮流,如果学一下就会了,那大数据行业现在恐怕已经被挤破门槛了吧,想学大数据还是得下苦功夫才行。 想学大数据,先把这几个技能学会再说: Apache Hive2.1 Hive是建立在Hadoop上的数据仓库基础构架。随着最新版本的发布,ApacheHive的性能和功能都得到了全面提升,它已成为SQL在大数据上的最佳解决方案。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL)——这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。 Hadoop 高效、可靠、可伸缩的Hadoop——能够为你的数据存储项目提供所需的YARN、HDFS和基础架构,并且运行主要的大数据服务和应用程序。 NiFi 堪称大数据工具箱里的瑞士军刀的ApacheNiFi,是由美国国家安全局(NSA)贡献给...
- 下一篇
老司机告诉你大数据开发:学Hadoop好还是Spark好?
相信看这篇文章的你们,都和我一样对Hadoop和Apache Spark的选择有一定的疑惑,今天查了不少资料,我们就来谈谈这两种 平台的比较与选择吧,看看对于工作和发展,到底哪个更好。 一、Hadoop与Spark 1.Spark Spark是一个用来实现快速而通用的集群计算的平台。速度方面,Spark扩展了广泛使用的MapReduce计算模型,而且高效地支持更多计算模式,包括交互式查询和流处理。 Spark项目包含多个紧密集成的组件。Spark的核心是一个对由很多计算任务组成的、运行在多个工作机器或者是一个计算集群上的应用进行调度、分发以及监控的计算引擎。 2.Hadoop Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。 二、异与同 解决问题的层面不一样 首先,Hadoop和Apache Spark两者都是大数据框架,但是各自存在的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Mario游戏-低调大师作品
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8