vlambda博客
学习文章列表

消灭重复类:同名类,同名方法,不同jar包,方法返回类型不一样,导致java.lang.NoSuchMethodError异常

消灭重复类:同名类,同名方法,不同jar包,方法返回类型不一样,导致java.lang.NoSuchMethodError异常

现象



由于项目中引入的两个不同的业务jar包,都包含了同名、同package,方法也基本相同,但是一个类中的一个方法的返回类型不同-方法签名不同,导致项目运行时,抛出java.lang.NoSuchMethodError异常。


两个jar包重复的类,属于copy代码所致,但是由于业务变动,一个jar包升级了此类的一个方法的返回类型,导致方法签名改变。


原因


涉及到类的加载问题,我们先复习下类的加载知识:




不同的类加载器,加载的类的路径是不一样的。类加载模型是双亲委派模型,即当前类加载时,先让其父类加载,只有当父类不能加载时,自己才会去加载。

如果同名类,同名方法,不同的jar包,所在文件系统中的路径不一样,属于不同的类加载器所加载,那么会根据类加载的父子关系决定。如果属于同一个类加载器所加载,可能根据先找到优先使用的原则。当然,这跟类加载器的实现有关系。


避免


同名类,同名方法,不同jar包中的类,会使运行时会抛出异常,我们必须避免这种现象的发生。

为了自动化检测我们可以使用maven enforcer-rules规则插件(https://maven.apache.org/enforcer/enforcer-rules/index.html)+Extra Enforcer Rules(https://www.mojohaus.org/extra-enforcer-rules/banDuplicateClasses.html)中的banDuplicateClasses规则


总结


同名类,同名方法,不同jar包,由于java的类加载机制,加载的顺序决定使用哪个jar包里的类。当这个重复类中出现不兼容的情况下,会导致运行时异常。