背景
有的时候,我们经常会碰到java.lang.NoSuchMethodError的错误信息。
究其根源,是由于JVM的 全盘负责委托机制导致的。
关于 全盘负责委托机制 ,请查看另一篇博文 全盘负责委托机制
特别是对于一些web项目,jar包很多,如何精确的查找呢?
方式一
将下面的JSP文件,放到web容器的根路径下,启动web容器,通过 http://ip:port/projectname/srcAdd.jsp?className=XXXXXX
比如:
运行web项目,访问
http://localhost:8080/hello-spring4/srcAdd.jsp?className=org.springframework.beans.factory.annota
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>
方式二
工具类 ClassLocationUtils.java
package com.xgj.master.ioc.classloaderUtil; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.security.CodeSource; import java.security.ProtectionDomain; /** * * @ClassName: ClassLocationUtils * @Description: tools to find which jar does the class come from * */ public class ClassLocationUtils { /** * find the location of the class come from * @param cls * @return */ public static String where(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(); if (pd != null) { final CodeSource cs = pd.getCodeSource(); if (cs != null) result = cs.getLocation(); if (result != null) { 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) { final ClassLoader clsLoader = cls.getClassLoader(); result = clsLoader != null ? clsLoader.getResource(clsAsResource) : ClassLoader.getSystemResource(clsAsResource); } System.out.println(result.toString()); return result.toString(); } }
运行查找
package com.xgj.master.ioc.classloader; import com.xgj.master.ioc.classloaderUtil.ClassLocationUtils; public class ClassLoaderTest { public static void main(String[] args) { // TODO Auto-generated method stub ClassLocationUtils.where(java.lang.Thread.class); } }
运行结果: