说说Jar包的管理

对于做Java的同学而言,应用依赖的那一众的Jar如何管理是个大难题,像我们的很多应用动不动就依赖上百个Jar,这些Jar的冲突问题很容易导致各种奇怪现象,例如有些机器是OK的,有些机器却报NoSuchMethodException等等,说说Jar管理中要解决的几个问题以及现在我们的解决方法,另外就是也希望能听到大家对这块的建议或者碰到过的问题。

Jar管理中最容易碰到的是这么几个问题:
1. Jar包版本冲突
这是最容易出现的现象,因为应用引用的Jar可能会再依赖其他的Jar,于是这种情况下会变得很不可控,通常来说用maven管理的java工程,在打包的时候会检查同样groupId和artifactId的依赖有没有出现版本冲突的现象,如果出现会禁止打包,这一定程度上缓解了依赖冲突的问题。

不知道大家碰到过多少那种改了groupId或artifactId,但里面类的包名什么的又没变的现象,反正我是碰过很多次了,对于这种状况Maven是提供不了什么帮助的,这种状况被发现通常会是由于应用启动或运行的时候报ClassNotFoundException或NoSuchMethodException,在启动参数上增加-XX:+TraceClassLoading有可能就会发现原来加载到了另外一个Jar,最龌龊的现象是某些jar把它依赖的jar的类也打包进去了。

Jar包版本冲突的问题绝对是Java应用不好解决的一个点,通常这类问题目前会采用这样一些方法来避免:
* 在pom.xml中写依赖的时候exclude掉依赖的某些依赖,避免依赖的依赖带来jar冲突;
* 对于实在找不出有冲突的jar是哪里造成的时候(至少我确实碰到过,即使用mvn dependency:tree也没找到),可以在pom.xml中直接写不想打入包中的那个jar的依赖,scope指定为provided,这样可以实现强制不把这个版本的jar打入包中;
* 在打包完成后,解开所有的jar,检查是否有完全同样的类名但类文件内容又不一致的现象,如果有则报错等,这种需要编写一个小的mvn插件来完成,或者也可以在一个打包脚本中最后用脚本来解决,这种千万不能存在侥幸心理,什么自己机器上是OK的,只要有类版本冲突,就是有可能会出现问题的,之所以在你的机器不出现只是可能凑巧装载的class是你应用需要的那个。

还有一类Jar包版本冲突问题可能是你的应用和容器的冲突,例如在jboss/tomcat里,尽管通常jboss/tomcat会提供classloader隔离的机制,但很多时候会出于某些需要关闭,这种时候就很容易导致容器的jar和应用的jar冲突的现象,这种是最不好搞的,因为只能是覆盖容器的。

ps: 真心希望Java能从语言级更好的解决依赖的问题,否则对于大型应用工程而言,Jar的冲突始终是个不太好处理的问题。

2. SnapShot包的问题
你的生产环境里跑的应用里依赖了多少SnapShot的包呢?这种是很容易造成极高的风险的,因为通常SnapShot的依赖在打包时会直接升级成最新的,而最新的这种有可能是有问题的,如果就这样打包后部署到生产环境,有可能会产生悲催的故障。
前两天我们在发布的时候就碰到过一次这个问题…
我们之前为了避免这类问题,是在打包的时候会检查是否有SnapShot的版本,有的话会禁止打包,但据说后来由于此类依赖太多,就去掉了,但从我们上面碰到的问题可以看到,这种问题是相当严重的…

3. 依赖了老的有bug的版本的Jar的问题
应用里依赖的无论是外部提供的Jar,还是公司内部其他团队提供的Jar,都有可能依赖的是有bug的版本,碰到这样的现象该怎么统一控制呢? 例如发邮件通知所有的开发,某个版本不能用? 通常来说这种通知都是无效的。
我们对于此类问题是写了一个maven插件,在打包时会增加一个依赖的jar包规则,例如当依赖的某个jar时,必须高于某版本,或不等于某版本,如果不符合的话则拒绝打包。
这个方法对一些需要升级jar版本的场景也会有帮助,例如提供的一个老版本的jar,可能希望在3个月后接口全部升级到新接口,于是可以在打包的时候提醒依赖的某个老版本的jar在几个月后会废弃,这样通常对升级会有一些帮助。

关于Jar包的管理,你有什么想说的吗,欢迎回复消息。

=============================
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。

《说说Jar包的管理》有2个想法

  1. 1.我们项目中也存在依赖上百个包的问题,但是我主张的解决办法是减少依赖,你能确认所有依赖的包都是有用的么??另外就是自己提供给外部的包,也尽量减少依赖
    2.snapshot的问题,如果禁用还是不太好的,毕竟有些包升级的比较频繁,你说的问题我们之前也遇到了,最后我们定的方案是,如果修改的代码和之前是兼容的,那版本号不变,如果不兼容那就升级版本号

发表评论

电子邮件地址不会被公开。 必填项已用*标注


*