前端开发 \ JavaScript \ Jar包冲突及java.lang.NoSuchMethodError异常解决方案

Jar包冲突及java.lang.NoSuchMethodError异常解决方案

总点击132
简介:版权声明:本文为博主原创文章,转载请写明出处。https://blog.csdn.net/wo541075754/article/details/48243403

版权声明:本文为博主原创文章,转载请写明出处。 https://blog.csdn.net/wo541075754/article/details/48243403

问题

在编码过程中,往往会遇到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>

意见反馈 常见问题 官方微信 返回顶部