- 背景
- 方式一
- 方式二
背景
有的时候,我们经常会碰到java.lang.NoSuchMethodError的错误信息。 究其根源,是由于JVM的 全盘负责委托机制导致的。 关于 全盘负责委托机制 ,请查看另一篇博文 全盘负责委托机制
特别是对于一些web项目,jar包很多,如何精确的查找呢?
方式一
将下面的JSP文件,放到web容器的根路径下,启动web容器,通过 http://ip:port/projectname/srcAdd.jsp?className=XXXXXX
比如:
运行web项目,访问
代码语言:javascript复制http://localhost:8080/hello-spring4/srcAdd.jsp?className=org.springframework.beans.factory.annotation.Autowired
srcAdd.jsp
代码语言:javascript复制<%@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.jartitle>
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("");
out.print(classLocation);
}
else {
out.print("类" className "没有对应的物理文件。");
out.print("错误:" error);
}
}catch(Exception e)
{
out.print("异常。" e.getMessage());
}
%>
body>
html>
方式二
工具类 ClassLocationUtils.java
代码语言:javascript复制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();
}
}
运行查找
代码语言:javascript复制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);
}
}
运行结果: