History

  • Xerces是Java生态圈使用最广泛的XML解析器,基本上所有的类库和框架都会在一定程度上使用它(即使没有直接引用,也有可能间接引用)
  • Xerces在官网中发布的包是没有标注版本的,2.11.0的jar命名为xercesImpl.jar而不是xercesImpl-2.11.0.jar.
  • Xerces不使用Maven,不会上传官方的release版本到Maven的中央仓库。
  • Xerces以前是发布一个jar包,但是之后分成两个jar包发布,一个包含API的xml-apis.jar和另一个包含其实现的xercesImpl.jar。许多老点儿的Maven Pom仍然依赖xerces.jar。更早的时候Xerces发布一个xmlParserAPIs.jar,也有些很古老很古老的pom会依赖这个jar。
  • 发布到Maven仓库的一些jar经常会依赖版本不同的xml-apis和xercesImpl。举例来说,依赖的xml-apis的版本可能是1.3.03而依赖的xercesImpl版本可能就是2.8.0,即使两个包都是来自
    Xerces 2.8.0。因为人们使用xml-apis.jar只想使用它某个版本的特定的API。
  • 更麻烦的是,JRE中JAXP(Java API for XML Processing)的Reference implementation(参考实现?)使用的XML解析器就是用的这个鸟Xerces。实现类被重新打包进了com.sun.,从而导致直接引用这些类很危险,因为他们在某些JRE中可能不会包含。然而,Xerces中并不是所有的方法都通过java.和javax.*的API暴露。举例来说,就没有实现Xerces序列化的API。
  • 基本上所有的servlet容器(JBoss, Jetty, Glassfish, Tomcat, ====),都包含一份或多份Xerces在他们的/lib包下。

问题

Maven解决jar包冲突

正是由于以上的一个或几个问题,许多组织会在他们的pom中重新构建自己的Xerces。当你的工程比较小而且你在用maven中央仓库的时候,这没什么问题。但是当你用Artifactory或者Nexus代理你的多个仓库时(JBoss的,Hibernate的,==),可能就出现问题了。

举例来说,A组织可能以如下方式依赖xml-apis:

<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>

而B组织可能以如下方式依赖同样的jar包:

<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>

尽管B的jar版本比A的jar版本低,但是maven并不知道他们俩是同一个artifact,因为两个jar的groupId不同,那么,最后maven解决版本的冲突而是把两个jar同时引入项目。如下图:

类加载器Hell

上面提到的,JRE会在JAXP RI中包含Xerces。当你把maven依赖的所有的Xerces都标记成<exclusion>或者<provided>虽然看起来没什么问题,但是你依赖的第三方代码可能和你使用的JDK中的JAXP中Xerces版本不兼容。除此之外,你还要应付servlet容器中的包含的Xerces。这给了你几个选择:
  • 删除servlet中的Xerces,然后祈祷你的容器可以在JAXP提供的版本上运行。
  • 保留servlet中的那个版本,然后祈祷你的应用框架可以在servlet提供的Xerces版本上正常运行。
  • 如果最后你的产品有那么一个或者两个没解决的版本冲突(如果你的应用很大的话,这是很容易出现的情况),你很快就会发现你正处于类加载器地狱(ClassLoader Hell),疑惑类加载器到底他妈的挑了那个版本在运行?在window或者linux上会不会挑同一个版本(很有可能不会)。

解决方案?

我们尝试把所有的Xerces的maven依赖标记成 或者,但是由于这鸟货的别名太多了(xml-apis, xerces, xercesImpl, xmlParserAPIs,====),这有时候并无卵用。另外,我们依赖的第三方包或者框架很可能不会跑在JAXP的版本或者servlet容器提供的Xerces版本上。
到底怎么解决?

目前他们的解决方案如下:
可以尝试使用maven enforcer插件中的banned dependency。这个rule可以让你禁止所有你不喜欢的别名,而且只会加入你喜欢的。

一个让java程序员有杀人的冲动的Xerces冲突问题的更多相关文章

  1. [转载]一个标准java程序员的进阶过程

    第一阶段:Java程序员 技术名称 内                 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...

  2. 面试挂了阿里却拿到网易offer,一个三年Java程序员的面试总结!

    前言 15年毕业到现在有三年多了,最近去面试了阿里集团(菜鸟网络,蚂蚁金服),网易,滴滴,点我达,最终收到点我达,网易offer,蚂蚁金服二面挂掉,菜鸟网络一个月了还在流程中... 最终有幸去了网易. ...

  3. 正式工作的前奏——一个Java程序员的实习总结(1)

    不知不觉,到深圳实习已经三个礼拜了.跟在暑假的三个半月实习不一样,这次收获更多,感受更好,算是摆脱了那次实习给我带来的阴影(这个会放到以后才说). 在知乎上,有这么一个问题,你现在最想跟刚工作时的你说 ...

  4. 做为一个Java程序员,你需要哪些傍身的技能?

    最近总有些断断续续的思考,想想从我入行以来,我到底学会了什么,做成过什么,以后要做什么,如何提升自己······· 工作3年了,常听人说3年,5年,10年是程序员的坎,每过一个都会有新的想法,新的改变 ...

  5. 如何成为一个优秀的java程序员

    Java程序员有许多应遵循的守则或最佳实践方式.本文概述了每个开发者最应该遵循的10条守则或戒律,如果不遵循它们,将会导致灾难性后果. 1. 为代码添加注释(Add comments to your ...

  6. 一个10年Java程序员的年终总结,献给还在迷茫中的你

    我越来越担心我作为一个Java程序员的未来. 恍然间,发现自己在这个行业里已经摸爬滚打将近10年了,原以为自己就凭已有的项目经验和工作经历怎么着也应该算得上是一个业内比较资历的人士了,但是今年在换工作 ...

  7. 0~5年一个Java程序员的晋升之路

    在程序界流行着一种默认的说法叫“黄金5年”,也就是一个程序员从入职的时候算起,前五年的选择直接影响着整个职业生涯中的职业发展方向和薪资走向,如何走好这5年,彻底从一个刚入行的菜鸟蜕变成可以以不变应万变 ...

  8. 一个3年Java程序员的坎与选择

    前言 LZ 15年本科毕业,不知不觉3年过去了,去年底裸辞回到成都来发展,年后开始找工作,面试了几家公司,现在整理整理做个总结,也方便规划下一个3到5年以及和广大想要进阶的Java程序员同胞们共勉. ...

  9. 对于长沙互联网发展,一个外来两年Java程序员的所见所感所愿

    惟楚有材,于斯为盛 本文有感于2019长沙互联网求职招聘大会,内容比较多,但都是我自己的一些所见.所感和所愿. 2019年3月的最后一天,参加2019长沙互联网求职招聘大会,看到了很多的招聘企业,也看 ...

  10. (转)java程序员进入名企需要掌握哪些,立一个flag

    想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,在面试之前到底需要准备哪些东西呢?面试时面试官想了解你的什么专业技能,以下都是一个合格Java软件工程师所要具备的. 一.专业技能 熟练的 ...

随机推荐

  1. 如何学习 Photoshop

    你有没有想过"图像处理或图形设计看起来很酷,我要学习 Photoshop!" 然后你第一次打开 Photoshop,并被你所看到的东西所震撼. Photoshop 是一款功能强大的 ...

  2. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.12.18)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  3. [转帖]解Bug之路-记一次JVM堆外内存泄露Bug的查找

    https://zhuanlan.zhihu.com/p/245401095 解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查 ...

  4. Oracle Rac 的简单学习

    Oracle Rac 的简单学习 Oracle RAC的概念 Oracle RAC (Real Application Clusters) 是 Oracle 数据库管理系统的一个功能, 它允许将数据库 ...

  5. [转帖]使用 Crash 工具分析 Linux dump 文件

    前言 Linux 内核(以下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪.开发者认为,内核如果发生了错误,就不应该继续运行.因此内核发生错误时,它的行为通常被设 ...

  6. buildkit 官网 service 资料

    [Unit]   Description=BuildKit   Requires=buildkit.socket   After=buildkit.socket   Documentation=htt ...

  7. MySQL备份恢复简单处理方法

    客户备份恢复的脚本处理简要如下: 首先登陆mysql服务器 方法如下: mysql -uroot -p 输入密码即可登陆 然后需要创建一个数据库, 个人感觉同名恢复最容易出问题 create data ...

  8. node中的优先从缓存中加载模块与模块的加载规则

    执行 node main.js 请问 b模块会被加载几次 //main.js require('./a.js') var fn = require('./b.js') console.log(fn.s ...

  9. 【分享一个工具】根据 /metrics 路径下的文本信息,自动生成包含所有 metrics 的 grafana 报表

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 在做某个服务对应的 grafana 监控报表的时候发现,一 ...

  10. 【JS 逆向百例】某空气质量监测平台无限 debugger 以及数据动态加密

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...