Jar包冲突及java.lang.NoSuchMethodError异常解决方案
2015-09-06 13:58
375 查看
问题
在编码过程中,往往会遇到jar包冲突的问题。问题的表现特征一般都是抛出java.lang.NoSuchMethodError异常。那么,今天就聊聊怎么解决此类问题。分析
此问题跟java的类加载机制有关。JVM装载类时使用“全盘负责委托机制”,此问题跟“委托机制”有关。它是指先委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。然而,如果在类路径下放置了多个不同版本的类包,如commons-lang 2.x.jar和commons-lang3.x.jar都位于类路径中,代码中用到了commons-lang3.x类的某个方法,而这个方法在commons-lang2.x中并不存在,JVM加载类时碰巧又从commons-lang 2.x.jar中加载类,运行时就会抛出NoSuchMethodError的错误。
问题排查
这种问题的排查是比较棘手的,特别是在Web应用的情况下,可作为类路径的系统目录比较多,特别在类包众多时,情况尤其复杂:你不知道JVM到底从哪个类包中加载类文件。下面提供一个srcAdd.jsp的程序,你把它放到Web应用的根路径下,通过如下方式即可查看JVM从哪个类包加载指定类(其中className为className参数为类的全名,不需要.class后缀,端口号为web项目的端口号,此处为80):
http://localhost/srcAdd.jsp?className=java.net.URL
srcAdd.jsp源码如下:
<%@page contentType="text/html; charset=GBK"%> <%@page import="java.security.*,java.net.*,java.io.*"%> <%! public static URL getClassLocation(final Class cls) { if (cls == null)throw new IllegalArgumentException("null input: cls"); URL result = null; final String clsAsResource = cls.getName().replace('.', '/').concat(".class"); final ProtectionDomain pd = cls.getProtectionDomain(); // java.lang.Class contract does not specify if 'pd' can ever be null; // it is not the case for Sun's implementations, but guard against null // just in case: if (pd != null) { final CodeSource cs = pd.getCodeSource(); // 'cs' can be null depending on the classloader behavior: if (cs != null) result = cs.getLocation(); if (result != null) { // Convert a code source location into a full class file location // for some common cases: if ("file".equals(result.getProtocol())) { try { if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip")) result = new URL("jar:".concat(result.toExternalForm()) .concat("!/").concat(clsAsResource)); else if (new File(result.getFile()).isDirectory()) result = new URL(result, clsAsResource); } catch (MalformedURLException ignore) {} } } } if (result == null) { // Try to find 'cls' definition as a resource; this is not // document.d to be legal, but Sun's implementations seem to //allow this: final ClassLoader clsLoader = cls.getClassLoader(); result = clsLoader != null ? clsLoader.getResource(clsAsResource) : ClassLoader.getSystemResource(clsAsResource); } return result; } %> <html> <head> <title>srcAdd.jar</title> </head> <body bgcolor="#ffffff"> 使用方法,className参数为类的全名,不需要.class后缀,如 srcAdd.jsp?className=java.net.URL <% try { String classLocation = null; String error = null; String className = request.getParameter("className"); classLocation = ""+getClassLocation(Class.forName(className)); if (error == null) { out.print("类" + className + "实例的物理文件位于:"); out.print("<hr>"); out.print(classLocation); } else { out.print("类" + className + "没有对应的物理文件。<br>"); out.print("错误:" + error); } }catch(Exception e) { out.print("异常。"+e.getMessage()); } %> </body> </html>
相关文章推荐
- eclipse servers 出错
- Jar包冲突及java.lang.NoSuchMethodError异常解决方案
- Java按名字set jdbc参数类
- spring中props,list,set,map元素的用法
- Eclipse在线汉化后打不开
- 关于JAVA项目中CLASSPATH路径详解
- java SingletonClass
- 欢迎使用CSDN-markdown编辑器
- ZOJ 3714 Java Beans
- Java主线程等待所有子线程执行完毕再执行解决办法集
- java在继承中父类的成员变量是否会被子类所覆盖
- java线程
- 为什么学java开发?
- java 大数加减法(小数,正负)
- SpringMVC中使用Interceptor拦截器
- Java Serializable(序列化)的理解和总结
- [Android]反编译apk + eclipse中调试smali
- JAR包不全!Unable to load configuration.-bean-jar:file:/.../struts2-core-2.2.1.jar!/struts-default.xml:7
- java 大数阶乘代码
- springmvc @ResponseBody 处理json返回406