jar包冲突导致的NoSuchMethodException或NoSuchFieldError异常

问题发生背景:在tomcat中部署web项目的时候,访问jsp文件时抛出java.lang.NoSuchMethodException异常
解决办法:最终发现tomcat自带的jsp相关jar包和项目中的jar包有冲突,移除项目中的冲突jar包后,项目发布正常,jsp可以正常访问;
 
问题定位总结
当一个项目使用的jar包越来越多,代码经常在运行的时候抛出异常:java.lang.NoSuchMethodException,java.lang.NoSuchFieldError,基本是存在多个jar包包含相同的class类文件导致的,运行期可能用的class没有该方法等。

从JVM类加载机制进行剖析:

a. Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作.
b. Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作
c. System ClassLoader(APPClassLoader)/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作.
d. User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.
 
JVM虚拟机采用双亲委托类加载机制,通过类加载器进行加载,Tomcat使用WebappClassLoader类加载器:
所以在Tomcat 6中默认情况下,Jar包的加载顺序是:
1)JDK_HOME/lib和JDK_HOME/lib/ext下的jar
2)Web应用WEB-INF\lib下的包
3)Tomcat\lib下的包
如果在WEB-INF\lib和Tomcat\lib下有包名类名完全相同的Class类被加载(由于版本不同等因素),那么在程序执行时,将无法判断具体使用哪一个Class,
从而会抛出java.lang.NoSuchMethodException或java.lang.NoSuchFieldError异常

 

猜你喜欢

转载自oitebody.iteye.com/blog/2225609